测试安卓requestLayout的工作流程


  • 前言

安卓控件方法当中,measure用于宽高的测量,layout用于指定控件的位置,  draw用于界面的渲染;不同层级的控件组成控件树,在界面生成的初始阶段是遍历树进行measure,然后是layout,最后是draw。已知的invalide()是用于View的界面强制重绘,即重新执行onDraw方法,那么另一个常见的requestLayout方法,一般解释是“

当view确定自身已经不再适合现有的区域时,该view本身调用这个方法要求parent view重新调用他的onMeasure onLayout来对重新设置自己位置。

”,那么具体是如何工作的呢?


  • 测试


            测试逻辑:通过自定义View和ViewGroup并加入日志;任意点击事件中执行两者的requestLayout方法并观察


    测试1:记录应用启动流程

    日志:

:inflate、attached
06-29 11:14:03.065: I/MyView(17365): ->onFinishInflate
06-29 11:14:03.065: I/MyView(17365): <-onFinishInflate
06-29 11:14:03.065: I/MyLinearLayout(17365): ->onFinishInflate
06-29 11:14:03.065: I/MyLinearLayout(17365): <-onFinishInflate
06-29 11:14:03.085: I/MyLinearLayout(17365): ->onAttachedToWindow
06-29 11:14:03.085: I/MyLinearLayout(17365): <-onAttachedToWindow
06-29 11:14:03.085: I/MyView(17365): ->onAttachedToWindow
06-29 11:14:03.085: I/MyView(17365): <-onAttachedToWindow
:measure、layout
06-29 11:14:03.085: I/MyLinearLayout(17365): ->onMeasure
06-29 11:14:03.085: I/MyLinearLayout(17365): ->measureChildWithMargins
06-29 11:14:03.085: I/MyView(17365): ->onMeasure
06-29 11:14:03.085: I/MyView(17365): <-onMeasure
06-29 11:14:03.085: I/MyLinearLayout(17365): <-measureChildWithMargins
06-29 11:14:03.085: I/MyLinearLayout(17365): <-onMeasure
06-29 11:14:03.085: I/MyLinearLayout(17365): ->onMeasure
06-29 11:14:03.085: I/MyLinearLayout(17365): ->measureChildWithMargins
06-29 11:14:03.085: I/MyView(17365): ->onMeasure
06-29 11:14:03.085: I/MyView(17365): <-onMeasure
06-29 11:14:03.085: I/MyLinearLayout(17365): <-measureChildWithMargins
06-29 11:14:03.085: I/MyLinearLayout(17365): <-onMeasure
06-29 11:14:03.105: I/MyLinearLayout(17365): ->onLayout
06-29 11:14:03.105: I/MyView(17365): ->layout
06-29 11:14:03.105: I/MyView(17365): ->onLayout
06-29 11:14:03.105: I/MyView(17365): <-onLayout
06-29 11:14:03.105: I/MyView(17365): <-layout
06-29 11:14:03.105: I/MyLinearLayout(17365): <-onLayout
:measure、layout
06-29 11:14:03.115: I/MyLinearLayout(17365): ->onMeasure
06-29 11:14:03.115: I/MyLinearLayout(17365): ->measureChildWithMargins
06-29 11:14:03.115: I/MyView(17365): ->onMeasure
06-29 11:14:03.115: I/MyView(17365): <-onMeasure
06-29 11:14:03.115: I/MyLinearLayout(17365): <-measureChildWithMargins
06-29 11:14:03.115: I/MyLinearLayout(17365): <-onMeasure
06-29 11:14:03.115: I/MyLinearLayout(17365): ->onMeasure
06-29 11:14:03.115: I/MyLinearLayout(17365): ->measureChildWithMargins
06-29 11:14:03.115: I/MyView(17365): ->onMeasure
06-29 11:14:03.115: I/MyView(17365): <-onMeasure
06-29 11:14:03.115: I/MyLinearLayout(17365): <-measureChildWithMargins
06-29 11:14:03.115: I/MyLinearLayout(17365): <-onMeasure
06-29 11:14:03.115: I/MyLinearLayout(17365): ->onLayout
06-29 11:14:03.115: I/MyView(17365): ->layout
06-29 11:14:03.115: I/MyView(17365): ->onLayout
06-29 11:14:03.115: I/MyView(17365): <-onLayout
06-29 11:14:03.115: I/MyView(17365): <-layout
06-29 11:14:03.115: I/MyLinearLayout(17365): <-onLayout
:draw
06-29 11:14:03.125: I/MyLinearLayout(17365): ->onDraw
06-29 11:14:03.125: I/MyLinearLayout(17365): <-onDraw
06-29 11:14:03.125: I/MyView(17365): ->onDraw
06-29 11:14:03.125: I/MyView(17365): <-onDraw


测试2:测试执行view.requestLayout

日志:

06-29 11:06:51.905: I/MyLinearLayout(15565): ->onMeasure
06-29 11:06:51.905: I/MyLinearLayout(15565): ->measureChildWithMargins
06-29 11:06:51.905: I/MyView(15565): ->onMeasure
06-29 11:06:51.905: I/MyView(15565): <-onMeasure
06-29 11:06:51.905: I/MyLinearLayout(15565): <-measureChildWithMargins
06-29 11:06:51.905: I/MyLinearLayout(15565): <-onMeasure
06-29 11:06:51.905: I/MyLinearLayout(15565): ->onMeasure
06-29 11:06:51.905: I/MyLinearLayout(15565): ->measureChildWithMargins
06-29 11:06:51.905: I/MyView(15565): ->onMeasure
06-29 11:06:51.905: I/MyView(15565): <-onMeasure
06-29 11:06:51.905: I/MyLinearLayout(15565): <-measureChildWithMargins
06-29 11:06:51.905: I/MyLinearLayout(15565): <-onMeasure
06-29 11:06:51.905: I/MyLinearLayout(15565): ->onLayout
(注:MyLinearLayout.layout为final方法,无法重写,所以此处应缺少其layout日志)
06-29 11:06:51.905: I/MyView(15565): ->layout
06-29 11:06:51.905: I/MyView(15565): ->onLayout
06-29 11:06:51.905: I/MyView(15565): <-onLayout
06-29 11:06:51.905: I/MyView(15565): <-layout
06-29 11:06:51.905: I/MyLinearLayout(15565): <-onLayout


测试3:设置view动态高度,如下:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

	Log.i(TAG, "->onMeasure");
	
	int measuredWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
	int measuredHeight = 50 * ++time;
	setMeasuredDimension(measuredWidth, measuredHeight);
	
	Log.i(TAG, "<-onMeasure");
}

,测试其requestLayout

日志:

06-29 11:02:31.785: I/MyLinearLayout(15016): ->onMeasure
06-29 11:02:31.785: I/MyLinearLayout(15016): ->measureChildWithMargins
06-29 11:02:31.785: I/MyView(15016): ->onMeasure
06-29 11:02:31.785: I/MyView(15016): <-onMeasure
06-29 11:02:31.785: I/MyLinearLayout(15016): <-measureChildWithMargins
06-29 11:02:31.785: I/MyLinearLayout(15016): <-onMeasure
06-29 11:02:31.785: I/MyLinearLayout(15016): ->onMeasure
06-29 11:02:31.785: I/MyLinearLayout(15016): ->measureChildWithMargins
06-29 11:02:31.785: I/MyView(15016): ->onMeasure
06-29 11:02:31.785: I/MyView(15016): <-onMeasure
06-29 11:02:31.785: I/MyLinearLayout(15016): <-measureChildWithMargins
06-29 11:02:31.785: I/MyLinearLayout(15016): <-onMeasure
06-29 11:02:31.785: I/MyLinearLayout(15016): ->onLayout
06-29 11:02:31.785: I/MyView(15016): ->layout
06-29 11:02:31.785: I/MyView(15016): ->onLayout
06-29 11:02:31.785: I/MyView(15016): <-onLayout
06-29 11:02:31.785: I/MyView(15016): <-layout
06-29 11:02:31.785: I/MyLinearLayout(15016): <-onLayout
:相比2,多处以下部分
06-29 11:02:31.785: I/MyLinearLayout(15016): ->onDraw
06-29 11:02:31.785: I/MyLinearLayout(15016): <-onDraw
06-29 11:02:31.795: I/MyView(15016): ->onDraw
06-29 11:02:31.795: I/MyView(15016): <-onDraw
06-29 11:02:31.805: I/MyLinearLayout(15016): ->onDraw
06-29 11:02:31.805: I/MyLinearLayout(15016): <-onDraw
06-29 11:02:31.805: I/MyView(15016): ->onDraw
06-29 11:02:31.805: I/MyView(15016): <-onDraw


测试3:执行group.requestLayout

日志:

06-29 11:00:39.295: I/MyLinearLayout(14655): ->onMeasure
06-29 11:00:39.295: I/MyLinearLayout(14655): ->measureChildWithMargins
06-29 11:00:39.295: I/MyLinearLayout(14655): <-measureChildWithMargins
06-29 11:00:39.295: I/MyLinearLayout(14655): <-onMeasure
06-29 11:00:39.295: I/MyLinearLayout(14655): ->onMeasure
06-29 11:00:39.295: I/MyLinearLayout(14655): ->measureChildWithMargins
06-29 11:00:39.295: I/MyLinearLayout(14655): <-measureChildWithMargins
06-29 11:00:39.295: I/MyLinearLayout(14655): <-onMeasure
06-29 11:00:39.295: I/MyLinearLayout(14655): ->onLayout
06-29 11:00:39.295: I/MyView(14655): ->layout
06-29 11:00:39.295: I/MyView(14655): <-layout
06-29 11:00:39.295: I/MyLinearLayout(14655): <-onLayout


测试4:执行group.getParent().requestLayout

日志:同上


  • 总结


拷贝转帖中的主要内容如下:


当一个View调用requestLayout的时候,会给当前的View设置一个FORCE_LAYOUT标记。由此向ViewParent请求布局。这样从这个View开始向上一直requestLayout。最终到达ViewRootImpl。ViewParent 就是当前的传输链。【参见职责链设计模式】


第一步。

ViewRootImpl发现请求了布局。那么就会调用measure方法。

measure方法确认当前View是否有FORCE_LAYOUT标记。

如果有,那么就会进行重新measure。并且设置标记LAYOUT_REQUIRED。


第二步。

 在随后的layout方法中,会判断这个标记。如果这个标记为true。

那么就一定会调用onLayout.

onLayout调用后清理LAYOUT_REQUIRED标记。

layout调用之后,会清理掉FORCE_LAYOUT标记。



综合测试和网友,简单整理如下:

1、requestLayout会为view添加FORCE_LAYOUT并逐级传递事件至根控件,之后再自上而下measure、layout

2、在必要的时候会触发执行draw事件,如宽高和位置的改变

3、对ViewGroup等中间层控件执行requestLayout,并不会导致其子控件onMeasure被调用,但onLayout会有




你可能感兴趣的:(安卓,requestlayout)