之前在写Spinner和ListView的文章中有提到过mBlockLayoutRequests、mInLayout这两个变量,现在就来简单说说这两个变量的作用吧。
先来看看源码注释吧
/**
* Indicates that this view is currently being laid out.
* 标志视图是否正在进行布局
*/
boolean mInLayout = false;
/**
* When set to true, calls to requestLayout() will not propagate up the parent hierarchy.
* This is used to layout the children during a layout pass.
* 当设置为true时,调用requestLayout()方法就不会传递到父布局
* 用于布局过程中
*/
boolean mBlockLayoutRequests = false;
AdapterView中只有在执行ItemSelected回调的时候用到:
void selectionChanged() {
// We're about to post or run the selection notifier, so we don't need
// a pending notifier.
mPendingSelectionNotifier = null;
if (mOnItemSelectedListener != null
|| AccessibilityManager.getInstance(mContext).isEnabled()) {
// 如果mInLayout或mBlockLayoutRequests使能,那么通过消息机制进行回调
// 否则直接进行回调
if (mInLayout || mBlockLayoutRequests) {
// If we are in a layout traversal, defer notification
// by posting. This ensures that the view tree is
// in a consistent state and is able to accommodate
// new layout or invalidate requests.
if (mSelectionNotifier == null) {
mSelectionNotifier = new SelectionNotifier();
} else {
removeCallbacks(mSelectionNotifier);
}
post(mSelectionNotifier);
} else {
dispatchOnItemSelected();
}
}
}
那ListView和Spinner是如何使用这两个变量的呢?
Spinner
其实Spinner并没有使用mInLayout,只是在onLayout方法中使能了mInLayout:
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mInLayout = true;
layout(0, false);
mInLayout = false;
}
mBlockLayoutRequests也只有在AbsSpinner中使用过一次,就是在requestLayout方法中:
@Override
public void requestLayout() {
if (!mBlockLayoutRequests) {
super.requestLayout();
}
}
然后在某些地方使能了改变量而已。
ListView
ListView也没有使用mInLayout和mBlockLayoutRequests,只是在两个地方分别使能了这两个变量:
boolean arrowScroll(int direction) {
try {
mInLayout = true;
final boolean handled = arrowScrollImpl(direction);
if (handled) {
playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction));
}
return handled;
} finally {
mInLayout = false;
}
}
@Override
protected void layoutChildren() {
final boolean blockLayoutRequests = mBlockLayoutRequests;
if (blockLayoutRequests) {
return;
}
mBlockLayoutRequests = true;
try{
// ...
}finally{
if (!blockLayoutRequests) {
mBlockLayoutRequests = false;
}
}
}
AbsListView中在两个地方使用了:
@Override
public void requestLayout() {
if (!mBlockLayoutRequests && !mInLayout) {
super.requestLayout();
}
}
public void setItemChecked(int position, boolean value) {
// ...
// 在布局过程中屏蔽Checked状态改变所引起的DataChanged事件
if (!mInLayout && !mBlockLayoutRequests) {
mDataChanged = true;
rememberSyncState();
requestLayout();
}
}
然后还有几个地方使能了这两个变量。
尾声
到这里,其实我们已经知道了这两个变量作用,以及在Spinner和ListView这两个类中的应用场景中的一些区别。其实还可以深入的,比如ListView在哪些地方使能了这两个变量,以及为什么?人懒,就先这样吧。。。
以上。