Activity生命周期和启动模式

1.Activity的生命周期的一点补充

关于Activity的声明周期可以参考官方文档,但是这里有一些细节需要拿出来说一下.

我们都知道Activity的生命周期中主要会调用如下函数:

  • onCreate():加载View,初始化组件,View即将可见,该状态不会停留很长时间,马上回调onStart方法.
  • onStart()
  • onResume():稳定状态(即我们平时所见到的状态)
  • onPause():部分不可见,例如上部显示了一个Dialog等(此处可以关闭掉声音,动画等,但不可以执行耗时操作,否则延长下一个Activity的显示时间)
  • onStop():完全不可见状态(执行一次关闭资源的操作,依然不能是耗时操作)
  • onDestroy():在Activity销毁的时候,关闭资源(数据库,文件,线程…)

假设这样一个简单的场景,我们的应用中有两个Acticity:A和B.点击应用进入A,A中有一个按钮,点击跳转到B,那么其生命周期会是怎样的呢?
(代码比较简单就不再贴了)之前我一直以为是这样的执行顺序:A.onCreate->A.onStart->A.onResume->点击跳转到B的按钮->A.onPause->A.onStop->B.onCreate->B.onStart->B.onResume

AB
onCreate
onStart
onResume
点击跳转到B的按钮
onPause
onStop
onCreate
onStart
onResume

但是一次实践后发现并不是这样的,其实际的执行顺序为:

AB
onCreate
onStart
onResume
点击跳转到B的按钮
onPause
onCreate
onStart
onResume
onStop

为什么会这样设计呢?
首先说为什么A->B,A会先Pause.试想一下这种情况,如果在当前Activity正在播放音乐,一个电话打过来,必须要有一个操作将当前的音乐关掉,所以需要一个状态,因此会先执行onPause.接下来的问题是,那onPause之后为什么不立即执行onStop,这是因为如果立即执行了onStop,Activity被完全隐藏并且对用户不可见;它被视为处于后台。那么假设进入B后,由于某种原因B无法显示,此时就应该显示的是A,可是A如果已经被stop了,就会出现短暂的黑屏,直到把A的布局重新加载出来后,在显示A.所以处于一种安全角度考虑,应该先将A pause后,立即加载B,直到B的onRsume执行后,表明B已是稳定态,在将A stop掉,这是一种更好的处理逻辑.

Activity的生命周期其在各种情况下的调用情况:
- 当进入一个界面时,会依次调用onCreate->onStart->onResume方法
- 当点击back键时,会依次调用onPause->onStop->onDestroy方法
- 当点击home键/菜单键时,会依次调用onPause->onSaveInstanceState->onStop
- 当在onCreate()方法内调用finish()时,会直接调用onDestroy方法而不经过onPause,onStop方法.
- 当屏幕旋转时,会依次调用:onPause->onSaveInstanceState->onStop->onDestroy->onCreate->onStart->onResume

2.Activity启动模式的一点补充

Activity的启动模式分为以下四种:

  1. standard:
  2. singleTop
  3. singleTask
  4. singleInstance

具体含义请参考官方文档

这里对singleTask和singleInstance做一些说明.

singleTask

singleTask的官方解释:系统创建新任务并实例化位于新任务底部的 Activity。但是,如果该 Activity 的一个实例已存在于一个单独的任务中,则系统会通过调用现有实例的 onNewIntent() 方法向其传送 Intent,而不是创建新实例。一次只能存在 Activity 的一个实例。

singleTask必须和TaskAffinity一起使用才能起作用

TaskAffinity,这个参数标识了该Activity所在的任务栈的名字.在默认情况下,其值就是清单文件里的声明的包名.当一个具有singleTask启动模式的Activity被启动后,系统首先会找是否存在其想要的任务栈,如何标识其任务栈呢?—就是TaskAffinity属性.TaskAffinity标志其所想要的任务栈.如果没有定义TaskAffinity属性,其默认值就是当前包名,所以就将该Activity创建在默认的任务栈,而不是一个新的栈.

我们还是用从A启动B的简单例子来描述,A的启动方式为默认的standard,B的启动方式声明为:singleTask,但是B没有定义TaskAffinity或者定义的singleTask为包名,那么很不幸,如果从A启动了B,B并不会被创建在一个新的任务中.这一点可以由getTaskId()方法来查看A和B的taskId是否一样,结果二者的ID是一样的.原因就是B没有定义一个新的TaskAffinity

singleInstance

singleInstance的官方解释:与”singleTask”相同,只是系统不会将任何其他Activity启动到包含实例的任务中。该 Activity始终是其任务唯一仅有的成员;由此Activity启动的任何Activity均在单独的任务中打开。

特别说明一下:与”singleTask”不同的是,指定了singleInstance启动模式的Activity,即使不指定TaskAffinity属性,该Activity依然自己待在一个独立的栈中,即使它和默认的任务栈的TaskAffinity是一样的,但是其taskId是不一样的.TaskAffinity相当于人的名字,taskId属于人的身份证号码.singleTask中指定了不同的TaskAffinity,那么必定不在同一个task中,但是singleInstance中强行指定了不同的taskId,那么即使TaskAffinity相同,也不是同一个task.(名字一样,身份证号不一样,依然是不同的栈!)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值