Android View的生命周期
View生命周期相关方法
View是什么?官方源码注释中的定义:这个类是用户接口的基础构件。View表示屏幕上的一块矩形区域,负责绘制这个区域和事件处理。
View是所有widget类的基类,Widget类用于创建交互式UI构件(按钮,输入框等)。
View类的ViewGroup子类是layout的基类,Layout是一个不可见的容器,它保存着View(或ViewGroup)并定义这些View的layout 属性。
简单点说,View就是屏幕上的一块矩形区域,我们可以在这块区域绘制我们想让用户看到的图形。
关于View的生命周期,官方源码注释中有详细的描述,作为英语六级勉强飘过的选手,我顶着巨大的压力翻译了一下。
- Creation(创建)
- Constructors(构造函数):有一种形式的构造函数会在View在代码中被创建时调用,另一种形式的构造函数会在View从layout加载出来时被调用。
第二种形式的构造函数会解析和应用layout文件中定义的任何属性。 - onFinishInflate():该方法当View及其子View从XML文件中加载完成后会被调用。
- Layout(布局)
- onMeasure(int, int):该方法在计算当前View及其所有子View尺寸大小需求时会被调用。
- onLayout(boolean, int, int, int, int):该方法在当前View需要为其子View分配尺寸和位置时会被调用。
- onSizeChanged(int, int, int, int):该方法在当前View尺寸变化时被调用。
- Drawing(绘制)
- onDraw(android.graphics.Canvas):该方法在当前View需要呈现其内容时被调用。
- Event processing(事件处理)
- onKeyDown(int, KeyEvent):该方法在一个物理按键事件发生时被调用。
- onKeyUp(int, KeyEvent):该方法在一个物理按键弹起事件发生时被调用。
- onTrackballEvent(MotionEvent):该方法在一个轨迹球运动事件发生时被调用。
- onTouchEvent(MotionEvent):该方法在一个触摸屏幕运动事件发生时被调用。
- Focus(聚焦)
- onFocusChanged(boolean, int, android.graphics.Rect):该方法在当前View获得或失去焦点时被调用。
- onWindowFocusChanged(boolean):该方法在包含当前View的window获得或失去焦点时被调用。
- Attaching(附上)
- onAttachedToWindow():该方法在当前View被附到一个window上时被调用。
- onDetachedFromWindow():该方法在当前View从一个window上分离时被调用。
- onVisibilityChanged(View, int):该方法在当前View或其祖先的可见性改变时被调用。
- onWindowVisibilityChanged(int):该方法在包含当前View的window可见性改变时被调用。
上述方法是View生命周期中涉及到的比较重要的一部分,View类中包含了很多的方法和属性,有兴趣的话各位可以自己研究一下。
View生命周期相关方法调用顺序
简单的了解了View生命周期相关的几个方法,接着我们看看这些方法调用的顺序是怎样的,我们针对View的可见性分三种情况来观察。
- android:visibility=visible
- 创建
I/TestView: TestView(Context context, AttributeSet attrs)
I/TestView: onFinishInflate()
I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{2192bad9 I.E..... R.....ID 0,0-0,0} visibility = 4
I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{2192bad9 V.E..... R.....ID 0,0-0,0} visibility = 0
I/TestView: onAttachedToWindow()
I/TestView: onWindowVisibilityChanged(int visibility) visibility = 0
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743848
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743848
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073744016
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073744016
I/TestView: onSizeChanged(int w, int h, int oldw, int oldh) w = 1328 h = 2192 oldw = 0 oldh0
I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = true left = 56 top = 56 right = 1384 bottom = 2248
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
I/TestView: onSizeChanged(int w, int h, int oldw, int oldh) w = 1328 h = 1996 oldw = 1328 oldh2192
I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = true left = 56 top = 56 right = 1384 bottom = 2052
I/TestView: onDraw(Canvas canvas)
I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = true
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = false left = 56 top = 56 right = 1384 bottom = 2052
I/TestView: onDraw(Canvas canvas)
- 销毁
I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = false
I/TestView: onWindowVisibilityChanged(int visibility) visibility = 8
I/TestView: onDetachedFromWindow()
- android:visibility=invisible
- 创建
I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.example.junyizhou.rxjavademo.TestView{3ead3d52 I.ED.... ........ 0,0-0,0} visibility = 4
I/TestView: TestView(Context context, AttributeSet attrs)
I/TestView: onFinishInflate()
I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{3aeb2b95 I.E..... R.....ID 0,0-0,0} visibility = 4
I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{3aeb2b95 V.E..... R.....ID 0,0-0,0} visibility = 0
I/TestView: onAttachedToWindow()
I/TestView: onWindowVisibilityChanged(int visibility) visibility = 0
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743848
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743848
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073744016
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073744016
I/TestView: onSizeChanged(int w, int h, int oldw, int oldh) w = 1328 h = 2192 oldw = 0 oldh0
I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = true left = 56 top = 56 right = 1384 bottom = 2248
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
I/TestView: onSizeChanged(int w, int h, int oldw, int oldh) w = 1328 h = 1996 oldw = 1328 oldh2192
I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = true left = 56 top = 56 right = 1384 bottom = 2052
I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = true
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = false left = 56 top = 56 right = 1384 bottom = 2052
- 销毁
I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = false
I/TestView: onWindowVisibilityChanged(int visibility) visibility = 8
I/TestView: onDetachedFromWindow()
- android:visibility=gone
- 创建
I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.example.junyizhou.rxjavademo.TestView{3ead3d52 G.ED.... ......I. 0,0-0,0} visibility = 8
I/TestView: TestView(Context context, AttributeSet attrs)
I/TestView: onFinishInflate()
I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{3aeb2b95 I.E..... R.....ID 0,0-0,0} visibility = 4
I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{3aeb2b95 V.E..... R.....ID 0,0-0,0} visibility = 0
I/TestView: onAttachedToWindow()
I/TestView: onWindowVisibilityChanged(int visibility) visibility = 0
I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = true
- 销毁
I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = false
I/TestView: onWindowVisibilityChanged(int visibility) visibility = 8
I/TestView: onDetachedFromWindow()
总结
从中我们可以看出:
- View默认为可见的,不是默认值时先调用onVisibilityChanged(),但是此时该View的尺寸、位置等信息都不知道。
- 可见性改变后才是调用带有两个参数的构造函数,当然,如果该View不是在layout中定义的话,会调用一个参数的构造函数。
- 从XMl文件中inflate完成(onFinishInflate())。
- 将View加到window中(View是gone的,那么View创建生命周期也就结束)。
- 测量view的长宽(onMeasure())。
- 定位View 在父View中的位置(onLayout()),若View是invisible,则View的创建生命周期结束。
- 绘制View的content(onDraw()),只有可见的View才在window中绘制。
- View的销毁流程和可见性没有关系。
综上所述:View的关键生命周期为:
[改变可见性] --> 构造View() --> onFinishInflate() --> onAttachedToWindow() --> onMeasure() --> onSizeChanged() --> onLayout() --> onDraw() --> onDetackedFromWindow()
自定义View时我们不可避免的要和View生命周期相关函数打交道,可能需要重新其中的某个或某几个来满足定制的需求,因此了解View的生命周期是Android程序猿进阶的必经之路。当然,我们没必要重新所有的方法,如果我们只是单纯的想把一个Bitmap画到View上,那我们只要重写View的onDraw方法就可以了,事实上自定义View的大部分情况我们也只是关注这个方法。
Android View的生命周期的更多相关文章
- Android开发——View的生命周期总结
0.前言 今天看到一个概念是View的生命周期,有点懵逼,听说过Activity的生命周期,Fragment的生命周期,对View的生命周期好像没什么概念啊.难道layout.draw这些也算是生命周 ...
- Android Activity的生命周期简单总结
Android Activity的生命周期简单总结 这里的内容参考官方的文档,这篇文章的目的不是去总结Activity是如何启动,如何创造,以及暂停和销毁的,而是从实际开发中分析在Activity各个 ...
- Android内的生命周期整理
1. Android App的生命周期: 2. Application的生命周期: 3. Activity的生命周期: 3.1 Fragment的生命周期: 4. Service的生命周期:5. Br ...
- Android开发——Activity生命周期
Android开发--Activity生命周期 Activity作为四大组件之首,也是使用最频繁的一种组件.本文将主要讲解Activity生命周期,包括正常情况下的Activity生命周期和异常情况下 ...
- 重温Android和Fragment生命周期
重温下Android和Fragment生命周期,理解生命周期方法的作用,什么时候调用,可以做一些什么操作. 1.Android生命周期 1.1 生命周期图 1.2 生命周期函数说明 onCreate: ...
- 创建控制器的方法、控制器加载view过程、控制器view的生命周期、多控制器组合
在介绍四大对象的那篇博客中,可以基本了解到程序启动的过程: main-->UIApplicationMain-->创建UIApplication的实例和app代理AppDelegate的实 ...
- android开发之生命周期
android开发之生命周期 一:Activity的生命周期: 这几天了了解了安卓Activity的生命周期,对于生命周期有了大概的理解: 一个Activity的生命周期也就是Activity从生成到 ...
- iOS开发——UI进阶篇(十)导航控制器、微博详情页、控制器的View的生命周期
一.导航控制器出栈 1.initWithRootViewController本质 UIViewController *vc = [[OneViewController alloc] init]; // ...
- View的生命周期
当一个进入一个新viewController的时候,viewController的view的生命周期一般是这样的: 1.先判断内存是否有这个View a.没有的话:生命周期为loadView-> ...
随机推荐
- android studio 运行是,app标题栏不显示
解决办法:让所有的活动都继承 AppCompatActivity就行了,如: public class FirstActivity extends AppCompatActivity{ ... }
- [PowerShell]–Checking the version of Office installed
– Create and initialize the object $objExcel = New-Object -ComObject Excel.Application – Query the v ...
- 微软企业库验证 Validations
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using S ...
- 13.php面向对象
1.构造函数 public __construct() {} 2.析构函数 public __destruct() {} 3.对象调用属性 //数以调用时候要用 -> 而不是Java的点. ...
- extern的原理很简单,就是告诉编译器:“你现在编译的文件中,有一个标识符虽然没有在本文件中定义,但是它是在别的文件中定义的全局变量,你要放行!”
extern的原理很简单,就是告诉编译器:“你现在编译的文件中,有一个标识符虽然没有在本文件中定义,但是它是在别的文件中定义的全局变量,你要放行!”
- shell正则式解析身份证和手机号
cat test2.html | sed -e 's/\(^\|[^0-9]\)\(13[0-9][0-9]\{8\}\|14[579][0-9]\{8\}\|15[0-3,5-9][0-9]\{8\ ...
- Piggy-Bank---hdu1114(完全背包)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1114 题意是有一个存钱罐,当它是空的时候重量为E,满的时候重量为F:已知存钱罐里面有 n 种钱,每种钱 ...
- 列表(List) 的增删改查及其他方法
一.列表的简介 列表是python中的基础数据类型之一,其他语言中也有类似于列表的数据类型,比如js中叫数组,他是以[ ]括起来,每个元素以逗号隔开,而且他里面可以存放各种数据类型比如:li = ...
- Erlang正则解析操作文件
-module(tool). %% ==================================================================== %% API functi ...
- Mysql学习笔记—索引
一.什么是索引 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,所以查询语句的优化显然是重中之重. 在数据 ...