关于Activity不得不说的一些知识点

来源:互联网 发布:钱程是个什么软件 编辑:程序博客网 时间:2024/06/06 14:12

  • Activity的生命周期的一点补充
  • Activity启动模式的一点补充
    • singleTask
    • singleInstance

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

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

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

A B 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
原创粉丝点击