Kevin Su bio photo

Kevin Su

patience, persevere, and enjoy

Email Github Stackoverflow
  1. Activity
  2. Service
  3. Fragment

Activity的生命周期还是很好理解的.

分成3个部分:

  1. 整个生命周期:就是从onCreate->onStart->onResume->onPause->onStop->onDestroy
  2. 可视周期:运行完onStart之后就可视,运行了onStop就不可视
  3. 前台运行周期:运行完onResume就是前台运行,运行onPause就是后台运行.

什么时候会改变生命周期,(正常的情况下,也就是没有被系统回收资源):

  1. 跳转新的Activity:原来的Activity会进入后台状态,或者暂停状态,
  2. 旋转屏幕:会销毁原来的Activity,重新构建新的Activity
  3. 点击home键:进入暂停状态
  4. 锁屏:进入暂停状态

Service的生命周期比Activity简单很多.

因为Service对应有两种启动方式,所以也就会有两种生命周期:

  1. 启动方式(startService, stopService): onCreate->onStartCommand(onStart)->onDestroy
  2. 绑定方式(bindService, unBindService): onCreate->onBind->onUnbind->onDestroy

通过启动方式使用Service,是在后台运行一个计算的服务,没有通信;通过绑定的Service,是可以通信的.

以本地Service来讲,(因为远程Service独占一个进程,那么该Service的生命周期,就与该进程有关),什么时候会修改生命周期:

  1. 杀掉进程
  2. 如果通过启动方式的话,通过stop的方式.
  3. 如果是绑定的方式,当屏幕方向发生改变的时候,且没有unBind的情况下,会抛异常,同时走onUnbind->onDestroy

Note:如果同一个Service被启动,同时被绑定,那么如果想销毁该Service,就需要stop并且unbind.

参考

最令人头晕的Fragment的生命周期.

首先Fragment只能嵌套在Activity中运行,存在于Activity视图中的某一个ViewGroup,通过FragmentManager来管理,所以Fragment的生命周期受Activity的生命周期的影响.
Activity管理着Fragment的返回栈,也就是改变一个事务,都可以将事务加入到事务栈中,以便点击返回键后返回上一个事务的状态.

添加一个Fragment到一个Activity,通常可以在XML中添加,或者直接在代码中添加,这对非常简单,但跟通常的情况,我们都是在一个Activity中切换多个Fragment.这个时候,我们可以通过两种方式来实现:

  1. 通过Replace的方式,替换对应Container中旧的Fragment
  2. 通过Add->Show->Hide->Remove的方式,添加多个Fragment到Container中,通过显示,隐藏的方式,切换Fragment.Show和Hide 不会影响Fragment的生命周期

Note:当然以上的这些操作,都必须通过FragmentTransaction把所有操作当成一个事务来处理,最后记得要commit.


对比Activity与Fragment之间的生命周期:

和Activity一样,Fragment也有几个周期:

  1. 整个周期:从onAttach -> …. -> onDetach
  2. 停止周期:在onDestroyView之后就是停止状态,这个时候片段不可见,或片段已经从Activity移除,但是被加入到返回栈中.
  3. 可视周期:从onStart->onStop
  4. 运行中周期:从onResume->onPause

Fragment和Activity之间的通信:Activity可以持有Fragment的实例,也可以通过findFragmentById或者findFragmentByTag来获取,而Fragment也可以获取Activity实例,通过getActivity.但是文档建议我们通过接口的方式来通信,因为同一个Fragment可以会在被嵌套的不同的Activity,使用接口的方式可以解耦.但是需要注意,Fragment不是一定attach到一个Activity,所以在通过getActivity获取Activity实例的时候,需要判断是否为null.

与Activity生命周期协调一致:

片段所在的 Activity 的生命周期会影响片段的生命周期,其表现为,Activity 的每次生命周期回调都会引发每个片段的类似回调。 例如,当 Activity 收到 onPause() 时,Activity 中的每个片段也会收到 onPause()。

不过,片段还有几个额外的生命周期回调,用于处理与 Activity 的唯一交互,以执行构建和销毁片段 UI 等操作。这些额外的回调方法是:

onAttach(): 在片段已与 Activity 关联时调用(Activity 传递到此方法内)。
onCreateView(): 调用它可创建与片段关联的视图层次结构。
onActivityCreated(): 在 Activity 的 onCreate() 方法已返回时调用。
onDestroyView(): 在删除与片段关联的视图层次结构时调用。
onDetach(): 在取消片段与 Activity 的关联时调用。

影响Fragment的生命周期的操作:

  1. Activity的生命周期会影响Fragment的生命周期,例如Activity调用onPause,onStop等等,都会影响Fragment,当然屏幕发生改变的时候,Activity受到影响,Fragment也就跟着发生改变,还有home键的点击.
  2. addToBackStack,加入栈的操作,这个时候Fragment会与Activity保持关联.所以Fragment不会回调onDestroy
  3. 使用onReplace往Container中加入Fragment的时候,走的生命周期都是onCreateView->onDestroyView,这个生命周期的意思是ViewGroup和Fragment之间的关联.

生命周期还会被系统影响,当资源紧张的时候,系统回收资源,这种情况下的生命周期与正常情况下有些不同.

如果要模拟资源回收这种情境,在真机中,可以通过在开发者模式中,设置不保留活动(就是每次跳转Activity的时候,都销毁原本的Activity),或者设置后台进程限制(当通过Home键或者启动其它App的时候,就会销毁上一个App).

Activity中提供了两个方法用于当资源回收的时候,保存和还原我们需要的数据.

  • onSaveInstanceState
  • onRestoreInstanceState

如果App都被回收了,那么当下一次启动的时候,application会重新onCreate.App被回收,会导致所有的静态变量都被销毁,所以需要注意,这个时候再使用原来的变量导致空指针的问题,需要重新初始化原来的值.

如果只是Activity被回收,就不会回收App中的静态变量,application也不会重新onCreate.onPause之后会调用onSaveInstanceState保存数据,在onStart后执行onRestoreInstanceState.同时,注意,onCreate的参数savedInstanceState会带着保存的数据,所以可以通过该参数中保存的数据,还原原来的View.

Fragment只提供了一个onSaveInstanceState方法,和Activity类似,在onCreate中恢复数据.

在测试App销毁的demo中遇到的问题:

在退到后台后,重新把App激活到前台的过程中,发现自己开发的app会出现一个短暂的白屏,然后重新绘制的过程.但是微信和QQ却可以自己打开,没有丝毫短暂白屏的情况.后面根据dumpsys命令发现,其实微信和QQ并没有被销毁.

参考1 参考2