我们知道,在android创建一个view有两种方式:
1. 在xml布局文件中配置,用LayoutInflater解析加载;
这两种的生命周期略有不同;
2. 直接在代码中new 出来;
首先看一下用LayoutInflater解析的方式,分3种情况:
android:visibility=”visible”(默认值)
解析加载过程
D/ViewLifeTime: ViewLifeTime: [context, attrs] D/ViewLifeTime: onFinishInflate: D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.android.internal.policy.impl.PhoneWindow$DecorView@5343b370], visibility = [4] D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.android.internal.policy.impl.PhoneWindow$DecorView@5343b370], visibility = [0] D/ViewLifeTime: onAttachedToWindow: D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [0] D/ViewLifeTime: onMeasure() called with: widthMeasureSpec = [1073742592], heightMeasureSpec = [1073742968] D/ViewLifeTime: onSizeChanged() called with: w = [768], h = [1144], oldw = [0], oldh = [0] D/ViewLifeTime: onLayout() called with: changed = [true], left = [0], top = [88], right = [768], bottom = [1232] D/ViewLifeTime: onWindowFocusChanged() called with: hasWindowFocus = [true] D/ViewLifeTime: onMeasure() called with: widthMeasureSpec = [1073742592], heightMeasureSpec = [1073742968] D/ViewLifeTime: onLayout() called with: changed = [false], left = [0], top = [88], right = [768], bottom = [1232] D/ViewLifeTime: onDraw() called with: canvas = [android.view.GLES20RecordingCanvas@53450f58]
按Home键进入后台
D/ViewLifeTime: onWindowFocusChanged() called with: hasWindowFocus = [false] D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [8] D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.android.internal.policy.impl.PhoneWindow$DecorView@5343b370], visibility = [4]
重新回到应用内
D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.android.internal.policy.impl.PhoneWindow$DecorView@5343b370], visibility = [0] D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [0] D/ViewLifeTime: onWindowFocusChanged() called with: hasWindowFocus = [true]
按back键
D/ViewLifeTime: onWindowFocusChanged() called with: hasWindowFocus = [false] D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [8] D/ViewLifeTime: onDetachedFromWindow:
invisible
解析加载过程D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.alex.ui.ViewLifeTime{42d34410 I.ED.... ........ 0,0-0,0}], visibility = [4] D/ViewLifeTime: ViewLifeTime: [context, attrs] D/ViewLifeTime: onFinishInflate: D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.android.internal.policy.impl.PhoneWindow$DecorView{42cbafc0 I.E..... R.....ID 0,0-0,0}], visibility = [4] D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.android.internal.policy.impl.PhoneWindow$DecorView{42cbafc0 V.E..... R.....ID 0,0-0,0}], visibility = [0] D/ViewLifeTime: onAttachedToWindow: D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [0] D/ViewLifeTime: onMeasure() called with: widthMeasureSpec = [10737429], heightMeasureSpec = [1073743422] D/ViewLifeTime: onSizeChanged() called with: w = [1080], h = [1598], oldw = [0], oldh = [0] D/ViewLifeTime: onLayout() called with: changed = [true], left = [0], top = [322], right = [1080], bottom = [1920] D/ViewLifeTime: onWindowFocusChanged() called with: hasWindowFocus = [true] D/ViewLifeTime: onMeasure() called with: widthMeasureSpec = [10737429], heightMeasureSpec = [1073743422] D/ViewLifeTime: onLayout() called with: changed = [false], left = [0], top = [322], right = [1080], bottom = [1920]
按Home键进入后台
D/ViewLifeTime: onWindowFocusChanged() called with: hasWindowFocus = [false] D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [8] D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.android.internal.policy.impl.PhoneWindow$DecorView{42cbafc0 I.E..... R....... 0,0-1080,1920}], visibility = [4]
重新回到应用内
D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [4] D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.android.internal.policy.impl.PhoneWindow$DecorView{42cbafc0 V.E..... R.....ID 0,0-1080,1920}], visibility = [0] ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [0] D/ViewLifeTime: onWindowFocusChanged() called with: hasWindowFocus = [true]
按back键返回
D/ViewLifeTime: onWindowFocusChanged() called with: hasWindowFocus = [false] D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [8] D/ViewLifeTime: onDetachedFromWindow:
gone
重新回到应用内
D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.alex.ui.ViewLifeTime{42d39300 G.ED.... ......I. 0,0-0,0}], visibility = [8] D/ViewLifeTime: ViewLifeTime: [context, attrs] ViewLifeTime: onFinishInflate: D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.android.internal.policy.impl.PhoneWindow$DecorView{42cbfeb0 I.E..... R.....ID 0,0-0,0}], visibility = [4] D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.android.internal.policy.impl.PhoneWindow$DecorView{42cbfeb0 V.E..... R.....ID 0,0-0,0}], visibility = [0] D/ViewLifeTime: onAttachedToWindow: D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [0] D/ViewLifeTime: onWindowFocusChanged() called with: hasWindowFocus = [true]
按Home键进入后台
D/ViewLifeTime: onWindowFocusChanged() called with: hasWindowFocus = [false] D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [8] D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.android.internal.policy.impl.PhoneWindow$DecorView{42cbfeb0 I.E..... R....... 0,0-1080,1920}], visibility = [4]
重新回到应用内
D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [4] D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.android.internal.policy.impl.PhoneWindow$DecorView{42cbfeb0 V.E..... R.....ID 0,0-1080,1920}], visibility = [0] D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [0] D/ViewLifeTime: onWindowFocusChanged() called with: hasWindowFocus = [true]
按back键返回
D/ViewLifeTime: onWindowFocusChanged() called with: hasWindowFocus = [false] D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [8] D/ViewLifeTime: onDetachedFromWindow:
其次再看一下直接new的view
D/ViewLifeTime: ViewLifeTime: [context]
D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.android.internal.policy.impl.PhoneWindow$DecorView{42cb63f8 I.E..... R.....ID 0,0-0,0}], visibility = [4]
D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.android.internal.policy.impl.PhoneWindow$DecorView{42cb63f8 V.E..... R.....ID 0,0-0,0}], visibility = [0]
D/ViewLifeTime: onAttachedToWindow:
D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [0]
D/ViewLifeTime: onMeasure() called with: widthMeasureSpec = [1073742904], heightMeasureSpec = [1073743744]
D/ViewLifeTime: onSizeChanged() called with: w = [1080], h = [1920], oldw = [0], oldh = [0]
D/ViewLifeTime: onLayout() called with: changed = [true], left = [0], top = [0], right = [1080], bottom = [1920]
D/ViewLifeTime: onWindowFocusChanged() called with: hasWindowFocus = [true]
D/ViewLifeTime: onMeasure() called with: widthMeasureSpec = [1073742904], heightMeasureSpec = [1073743744]
D/ViewLifeTime: onLayout() called with: changed = [false], left = [0], top = [0], right = [1080], bottom = [1920]
D/ViewLifeTime: onDraw() called with: canvas = [android.view.GLES20RecordingCanvas@42cd9770]
按home键进入后台
D/ViewLifeTime: onWindowFocusChanged() called with: hasWindowFocus = [false]
D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [8]
D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.android.internal.policy.impl.PhoneWindow$DecorView{42cb63f8 I.E..... R.....I. 0,0-1080,1920}], visibility = [4]
重新回到应用内
D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [4]
D/ViewLifeTime: onVisibilityChanged() called with: changedView = [com.android.internal.policy.impl.PhoneWindow$DecorView{42cb63f8 V.E..... R.....ID 0,0-1080,1920}], visibility = [0]
D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [0]
D/ViewLifeTime: onDraw() called with: canvas = [android.view.GLES20RecordingCanvas@42cd9770]
D/ViewLifeTime: onWindowFocusChanged() called with: hasWindowFocus = [true]
按back键返回
D/ViewLifeTime: onWindowFocusChanged() called with: hasWindowFocus = [false]
D/ViewLifeTime: onWindowVisibilityChanged() called with: visibility = [8]
D/ViewLifeTime: onDetachedFromWindow:
由测试可以看出
1.对于从xml中解析的view:如果visibility不是visible(默认值)时,会先回调onVisibilityChanged()(invisible 会设置为invisible,gone会设置成 visible),然后在调用构造方法
2.onVisibilityChanged()会被回调多次
visible: 会先设置为invisible 在改为visible
invisible: 在构造方法之前设置为invisible,构造方法之后先设置为invisible,再改为visible
gone:在构造方法之前设置为visible,构造方法之后先设置为invisible,再改为visible
不知道为什么最后一次都设置为了visible?难道是log顺序错
3.对于从xml中解析的需要注意onFinishInflate(),在解析过程中会根据xml中的配置设置view的属性,因此如果要在代码中设置view的参数,要在activity的onFinishInflate()方法中或之后的设置,防止被覆盖
4.onMeasure()和onLayout()会回调至少两次,在第一次回调onMeasure()后会回调onSizeChanged(),因此如果在自定义view中需要view的width 和 height可以再onSizeChanged中获得;在最后一次onLayout()之后会回调onDraw()绘制view
5.onAttachedToWindow() 和 onDetachedFromWindow()对应:可以在onDetachedFromWindow()中释放需要释放的资源
6.onWindowFocusChanged()监听view所在window的焦点情况,可以作为view是否在前台的标志