Activity、Fragment、Service、View生命周期
1. Activity 生命周期
onCreate : 该方法是在Activity被创建时回调,它是生命周期第一个调用的方法,我们在创建Activity时一般都需要重写该方法,然后在该方法中做一些初始化的操作,如通过setContentView设置界面布局的资源,初始化所需要的组件信息等。
onStart : 此方法被回调时表示Activity正在启动,此时Activity已处于可见状态,只是还没有在前台显示,因此无法与用户进行交互。可以简单理解为Activity已显示而我们无法看见摆了。
onResume : 当此方法回调时,则说明Activity已在前台可见,可与用户交互了(处于前面所说的Active/Running形态),onResume方法与onStart的相同点是两者都表示Activity可见,只不过onStart回调时Activity还是后台无法与用户交互,而onResume则已显示在前台,可与用户交互。当然从流程图,我们也可以看出当Activity停止后(onPause方法和onStop方法被调用),重新回到前台时也会调用onResume方法,因此我们也可以在onResume方法中初始化一些资源,比如重新初始化在onPause或者onStop方法中释放的资源。
onPause : 此方法被回调时则表示Activity正在停止(Paused形态),一般情况下onStop方法会紧接着被回调。但通过流程图我们还可以看到一种情况是onPause方法执行后直接执行了onResume方法,这属于比较极端的现象了,这可能是用户操作使当前Activity退居后台后又迅速地再回到到当前的Activity,此时onResume方法就会被回调。当然,在onPause方法中我们可以做一些数据存储或者动画停止或者资源回收的操作,但是不能太耗时,因为这可能会影响到新的Activity的显示——onPause方法执行完成后,新Activity的onResume方法才会被执行。
onStop : 一般在onPause方法执行完成直接执行,表示Activity即将停止或者完全被覆盖(Stopped形态),此时Activity不可见,仅在后台运行。同样地,在onStop方法可以做一些资源释放的操作(不能太耗时)。
onRestart :表示Activity正在重新启动,当Activity由不可见变为可见状态时,该方法被回调。这种情况一般是用户打开了一个新的Activity时,当前的Activity就会被暂停(onPause和onStop被执行了),接着又回到当前Activity页面时,onRestart方法就会被回调。
onDestroy :此时Activity正在被销毁,也是生命周期最后一个执行的方法,一般我们可以在此方法中做一些回收工作和最终的资源释放。
2. Fragment 生命周期
Fragment每个生命周期方法的意义、作用(注意红色的不是生命周期方法):
setUserVisibleHint():设置Fragment可见或者不可见时会调用此方法。在该方法里面可以通过调用getUserVisibleHint()获得Fragment的状态是可见还是不可见的,如果可见则进行懒加载操作。
onAttach():执行该方法时,Fragment与Activity已经完成绑定,该方法有一个Activity类型的参数,代表绑定的Activity,这时候你可以执行诸如mActivity = activity的操作。
onCreate():初始化Fragment。可通过参数savedInstanceState获取之前保存的值。
onCreateView():初始化Fragment的布局。加载布局和findViewById的操作通常在此函数内完成,但是不建议执行耗时的操作,比如读取数据库数据列表。
onActivityCreated():执行该方法时,与Fragment绑定的Activity的onCreate方法已经执行完成并返回,在该方法内可以进行与Activity交互的UI操作,所以在该方法之前Activity的onCreate方法并未执行完成,如果提前进行交互操作,会引发空指针异常。
onStart():执行该方法时,Fragment由不可见变为可见状态。
onResume():执行该方法时,Fragment处于活动状态,用户可与之交互。
onPause():执行该方法时,Fragment处于暂停状态,但依然可见,用户不能与之交互。
onSaveInstanceState():保存当前Fragment的状态。该方法会自动保存Fragment的状态,比如EditText键入的文本,即使Fragment被回收又重新创建,一样能恢复EditText之前键入的文本。
onStop():执行该方法时,Fragment完全不可见。
onDestroyView():销毁与Fragment有关的视图,但未与Activity解除绑定,依然可以通过onCreateView方法重新创建视图。通常在ViewPager+Fragment的方式下会调用此方法。
onDestroy():销毁Fragment。通常按Back键退出或者Fragment被回收时调用此方法。
onDetach():解除与Activity的绑定。在onDestroy方法之后调用。
Fragment生命周期执行流程(注意红色的不是生命周期方法):
Fragment创建:setUserVisibleHint()->onAttach()->onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume();
Fragment变为不可见状态(锁屏、回到桌面、被Activity完全覆盖):onPause()->onSaveInstanceState()->onStop();
Fragment变为部分可见状态(打开Dialog样式的Activity):onPause()->onSaveInstanceState();
Fragment由不可见变为活动状态:onStart()->OnResume();
Fragment由部分可见变为活动状态:onResume();
退出应用:onPause()->onStop()->onDestroyView()->onDestroy()->onDetach()(注意退出不会调用onSaveInstanceState方法,因为是人为退出,没有必要再保存数据);
Fragment被回收又重新创建:被回收执行onPause()->onSaveInstanceState()->onStop()->onDestroyView()->onDestroy()->onDetach(),重新创建执行onAttach()->onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume()->setUserVisibleHint();
横竖屏切换:与Fragment被回收又重新创建一样。
3. Service 生命周期
在Service
的生命周期里,常用的有:
- 4个手动调用的方法
手动调用方法 | 作用 |
---|---|
startService() | 启动服务 |
stopService() | 关闭服务 |
bindService() | 绑定服务 |
unbindService() | 解绑服务 |
- 5个自动调用的方法
内部自动调用的方法 | 作用 |
---|---|
onCreat() | 创建服务 |
onStartCommand() | 开始服务 |
onDestroy() | 销毁服务 |
onBind() | 绑定服务 |
onUnbind() | 解绑服务 |
4. View 生命周期
View的关键生命周期为:
[改变可见性] --> 构造View() --> onFinishInflate() --> onAttachedToWindow()
--> onMeasure() --> onSizeChanged() --> onLayout() --> onDraw()
--> onDetackedFromWindow()
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()
上一篇: 46 FinalReference.referent的回收时机
下一篇: 浅谈Python C扩展
推荐阅读
-
Activity、Fragment、Service、View生命周期
-
Android学习笔记(Android Studio) 4-1-2 Activity的生命周期(不可不会的Activity和Fragment)
-
Android中Fragment与Activity的生命周期对比
-
Android中Fragment与Activity的生命周期对比
-
面试常问知识点,Fragment+Activity+service等等 AndroidBAT面试activityFragmentservice
-
Activity和Fragment生命周期
-
Fragment与Activity之间生命周期的关系
-
Android Activity和Fragment生命周期
-
Fragment生命周期和Activity通讯方法
-
Android基础常用组件——Fragment的创建,生命周期,与Activity通信,结合ViewPager使用的预加载和懒加载