【参考链接】
requestLayout调用onDraw之谜http://blog.csdn.net/litefish/article/details/52682152
Ps.基于android-2.3.3_r1源码及模拟器,不同版本可能略有不同。
在跟View相关的地方,经常会用到requestLayout()和invalidate()方法。这两个方法分别有什么用呢?
requestLayout()
从《Activity、Window、View执行流程概述[2]》可知,requestLayout()会将ViewRoot的mLayoutRequested置true,然后向主线程发送一个DO_TRAVERSAL消息。执行performTraversal()方法,因mLayoutRequested=true,所以会执行一次measure()、layout()。
但是,只有当View的长宽位置发生改变的时候,才会执行draw()步骤,因为,只有View的长宽发生改变,才会将该View的区域添加到ViewRoot的mDirty中,只有mDirty.isEmpty()!=null,才会执行draw()步骤。
invalidate()
invalidate()会将View的自身区域合并到ViewRoot的mDirty中去,然后向主线程发送一个DO_TRAVERSAL消息。执行performTraversal()方法,因mLayoutRequested!=true,所以只会执行一次draw()。
另外,上面在分析Activity、Window、View流程的时候,invalidate()都是在主线程中执行的。View还提供了postInvalidate()方法用于在非主线程中使用。
以如下代码为例
<com.example.root.myapplication.MyTextView
android:id="@+id/tv"
android:layout_width="200px"
android:layout_height="200px"
android:text="Hello World!"
android:background="@android:color/white"
android:textColor="@android:color/black"/>
private
voidinit() {
this.setOnClickListener(newOnClickListener()
{
@Override
public voidonClick(View
view) {
Log.e("shadowfaxghh","MyTextView onClick()");
FrameLayout.LayoutParamslayoutParams = (FrameLayout.LayoutParams) MyTextView.this.getLayoutParams();
layoutParams.width=100;
layoutParams.height=100;
layoutParams.leftMargin=100;
layoutParams.topMargin=100;
// MyTextView.this.requestLayout();
MyTextView.this.invalidate();
}
});
}
执行requestLayout()时的输出如下
执行invalidate()时的输入如下
而在较高的版本上,比如说如下Log所在的5.1版本,invalidate()也触发了重新draw(),不过并没有由父ViewGroup派发