11.Activity启动模式

Android中Activity四种启动模式和taskAffinity属性详解

Application,Task和Process

  1. Application是一组组件的集合
  2. task是一组相互关联的activity的集合
    task是可以跨应用的,这正是task存在的一个重要原因。有的Activity,虽然不在同一个app中,但为了保持用户操作的连贯性,把他们放在同一个任务中。例如,在我们的应用中的一个Activity A中点击发送邮件,会启动邮件程序的一个Activity B来发送邮件,这两个activity是存在于不同app中的,但是被系统放在一个任务中,这样当发送完邮件后,用户按back键返回,可以返回到原来的Activity A中,这样就确保了用户体验。
  3. 在默认情况下,一个应用程序的所有组件运行在同一个进程中。但是这种情况也有例外,即,应用程序中的不同组件可以运行在不同的进程中。只需要在manifest中用process属性指定组件所运行的进程的名字。

1. standard

每次都会实例化一个。

2. singleTop

  1. 如果一个以singleTop模式启动的activity的实例已经存在于任务桟的桟顶,那么再启动这个Activity时,不会创建新的实例,而是重用位于栈顶的那个实例,并且会调用该实例的onNewIntent()方法将Intent对象传递到这个实例中。
  2. 如果以singleTop模式启动的activity的一个实例已经存在与任务桟中,但是不在桟顶,那么它的行为和standard模式相同,也会创建多个实例。

3. singleTask

把启动模式设置为singleTask,framework在启动该activity时只会把它标示为可在一个新任务中启动(类似FLAG_ACTIVITY_NEW_TASK),至于是否在一个新任务中启动,还要受其他条件的限制。

**taskAffinity**是manifest文件中的一个重要属性
1. taskAffinity表示当前activity具有亲和力的一个任务,这个taskAffinity表示一个任务,这个任务就是当前activity所在的任务。
在概念上,具有相同的affinity的activity(即设置了相同taskAffinity属性的activity)属于同一个任务。
2. 默认情况下,**一个应用中的所有activity具有相同的taskAffinity**,即应用程序的包名。我们可以通过设置不同的taskAffinity属性给应用中的activity分组,也可以把**不同的应用中的activity的taskAffinity设置成相同的值**。
3. 为一个activity的taskAffinity设置一个空字符串,表明这个activity不属于任何task。
**SecondActivity没设置singleTask,设置taskAffinity的情况:**
a. 如果存在这样的一个任务,则检查在这个任务中是否已经有了一个SecondActivity的实例,如果已经存在一个SecondActivity的实例,则会重用这个任务和任务中的SecondActivity实例,将这个任务调到前台,清除位于SecondActivity上面的所有Activity,显示SecondActivity,并调用SecondActivity的onNewIntent();
b.如果不存在一个SecondActivity的实例,会在这个任务中创建SecondActivity的实例,并调用onCreate()方法
如果不存在这样的一个任务,会创建一个新的affinity为com.jg.zhang.androidtasktest.second的任务,并且将SecondActivity启动到这个新的任务中.
**SecondActivity只设置启动模式为singleTask,而不设置taskAffinity,即三个Activity的taskAffinity相同,都为应用的包名,那么SecondActivity是不会开启一个新任务的**
1. 在MainActivity启动SecondActivity时,发现启动模式为singleTask,那么设定他的启动标志为FLAG_ACTIVITY_NEW_TASK
2. 然后获得SecondActivity的taskAffinity,即为包名com.jg.zhang.androidtasktest
3. 检查是否已经存在一个affinity为com.jg.zhang.androidtasktest的任务,这个任务是存在的,就是MainActivity所在的任务,这个任务是在启动MainActivity时开启的
4. 既然已经存在这个任务,就检索在这个任务中是否存在一个SecondActivity的实例,发现不存在
5.在这个已有的任务中启动一个SecondActivity的实例
**SecondActivity启动模式设为singleTask,并且taskAffinity设为com.jg.zhang.androidtasktest.second时的启动过程:
1. 在MainActivity启动SecondActivity时,发现启动模式为singleTask,那么设定他的启动标志为FLAG_ACTIVITY_NEW_TASK
2. 然后获得SecondActivity的taskAffinity,即com.jg.zhang.androidtasktest.second
3. 检查是否已经存在一个affinity为com.jg.zhang.androidtasktest.second的任务,这个任务是不存在的
4. 创建一个新的affinity为com.jg.zhang.androidtasktest.second的任务,并且将SecondActivity启动到这个新的任务中
两个不同app中的不同的singleTask模式的Activity的taskAffinity设成相同验证:**任务(Task)不仅可以跨应用(Application),还可以跨进程(Process)**

4. singleInstance

singleInstance的特点可以归结为以下三条:

  1. 以singleInstance模式启动的Activity具有全局唯一性,即整个系统中只会存在一个这样的实例
  2. 以singleInstance模式启动的Activity具有独占性,即它会独自占用一个任务,被他开启的任何activity都会运行在其他任务中(官方文档上的描述为,singleInstance模式的Activity不允许其他Activity和它共存在一个任务中)
  3. 被singleInstance模式的Activity开启的其他activity,能够开启一个新任务,但不一定开启新的任务,也可能在已有的一个任务中开启

使用场景

  1. singleTop
    解决问题:由于栈顶都是相同Activity而导致用户出现BACK键失灵的错觉
    a. APP的多个推送消息显示在通知栏,你想把他们都给点了,每次点击实际就是启动某个Activity,这时候如果使用的是singleTop模式,就可以有效避免重复创建同一Activity实例的工作。
    b. 登录成功跳转到主页,按下两次登录按钮,生成了两个主页。一些有启动延迟的页面(往往是动画,网络造成)也会有这样的情况。
  2. singleTask
    创建开销较大且经常被其他APP调用的Activity中使用,这种Activity一般作为程序的入口。例如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。
  3. singleInstance
    单一实例模式,整个手机操作系统里面只有一个实例存在。不同的应用去打开这个activity共享公用的同一个activity。这样的Activity封闭性极强,能够很好地保持唯一性,也能大大减少不必要的开销。
    某个应用中用到了google地图 当退出该应用的时候,进入google地图,还是刚才的界面.
    闹铃的响铃界面 你以前设置了一个闹铃:上午6点。在上午5点58分,你启动了闹铃设置界面,并按 Home 键回桌面;在上午5点59分时,你在微信和朋友聊天;在6点时,闹铃响了,并且弹出了一个对话框形式的 Activity(名为 AlarmAlertActivity) 提示你到6点了(这个 Activity 就是以 SingleInstance 加载模式打开的),你按返回键,回到的是微信的聊天界面,这是因为 AlarmAlertActivity 所在的 Task 的栈只有他一个元素, 因此退出之后这个 Task 的栈空了。如果是以 SingleTask 打开 AlarmAlertActivity,那么当闹铃响了的时候,按返回键应该进入闹铃设置界面。

你可能感兴趣的:(11.Activity启动模式)