学习笔记| (二) 组件篇之Activity启动模式

一.启动模式:

1.Standard
  • 默认是standard模式
  • A启动B,B就会进入A所在的任务栈中
  • 不管要启动的activity在任务栈中是否存在,都会重新创建一个新的实例
  • 在Activity A中不断的启动自己
android:launchMode="standard"
MainActivity-->com.code.MainActivity@2cdaf713-->栈:885
MainActivity-->com.code.MainActivity@2d2219ca-->栈:885
MainActivity-->com.code.MainActivity@177c5ca6-->栈:885
2.SingleTop
  • A启动B,B就会进入A所在的任务栈中
  • 要启动的Activity如果处于栈顶,不会创建新的实例,而会调用onNewIntent()方法;如果不在栈顶,则会创建新的实例;
  • B的启动方式是SingleTop,A中启动B,在B中再启动B
android:launchMode="singleTop"
A:MainActivity-->com.code.MainActivity@2cdaf713-->栈:887
B:onCreate-->com.code.BActivity@2d2219ca-->栈:887
B:onNewIntent-->com.code.BActivity@2d2219ca-->栈:887
B:onNewIntent-->com.code.BActivity@2d2219ca-->栈:887
3.SingleTask
  • 启动A,会先看是否存在A想要的任务栈,不存在,创建任务栈,把A放进去;存在,判断是否存在A的实例,存在,则会调用onNewIntent(),默认具有clearTop的效果,会清空它上面的所有activity,让它们出栈,并将要启动的activity置于栈顶;否则会创建新的实例;
  • B的启动模式是SingleTask,A启动B,B启动C,C中再启动B
android:launchMode="singleTask"
A:MainActivity-->com.code.MainActivity@2cdaf713-->栈:889
B:onCreate-->com.code.BActivity@2d2219ca-->栈:889
C:onCreate-->com.code.CActivity@1490bfe8-->栈:889
B:onNewIntent-->com.code.BActivity@2d2219ca-->栈:889
4.SingleInstance
  • A启动B,B会进入一个新的任务栈中
  • SingleInstance是SingTask的升级版,它具有SingleInstance的所有特性,要启动的Activity会在一个新的任务栈中创建,如果之后要再启动这个Activity,先看任务栈中是否存在这个Activity,存在,调用onNewIntant(),并将上面的Activity清空;否则创建一个新的实例;
  • B的启动模式是SingleInstance,A启动B后,B再启动B
android:launchMode="singleInstance"
A:MainActivity-->com.code.MainActivity@2cdaf713-->栈:892
B:onCreate-->com.code.BActivity@2d2219ca-->栈:893
B:onNewIntent-->com.code.BActivity@2d2219ca-->栈:893

注意

getApplication().startActivity(new Intent(this,BActivity.class));

如果这样启动一个Activity,会报错:

Caused by: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

之前在项目中,来电时会出一个Activity,就报了这个错,这个错是什么原因导致的呢?
因为getApplication()是非Activity类型的context,并不存在任务栈一说,所以启动B的时候,B会添加到getApplication()所在的任务栈,这就矛盾了,这时候并不存在任务栈,所以只能将B添加到一个新的任务栈中

任务栈

  • 分为前台任务栈和后台任务栈
  • SingleTask中多次提到了任务栈,那么什么是任务栈呢?
    这里涉及到一个名词“TaskAffinity”,可以叫“任务相关性”,它是任务栈的名字,所有Activity都默认是包名。
  • TaskAffinity只有和"SingleTask"
    或者“allowTaskReparenting”一起使用时才起作用,如果TaskAffinity指定为当前包名,也是无效的,因为默认就是包名,没啥用处。
  • TaskAffinity和"SingleTask"一起使用

也就是所有taskAffinity相同的会在一个任务栈中存在;

  • TaskAffinity和"allowTaskReparenting"一起使用, app A启动了 app B的 Activity C(allowTaskReparenting为true),这时候启动app B了,那么在B上显示的是哪一个页面呢?
    答案是Activity C。
    分析:
    A启动了页面c,这时候c的TaskAffinity和A的TaskAffinity肯定不同,但是又没有c所需要的任务栈存在,所以c只能现在A的任务栈中运行,这时候B打开了,系统发现c所需要的任务栈存在了,就会将c移到B的任务栈中,所以会看到B上显示的是c页面。

  • A,B,C三个Activity,B和C的TaskAffinity为com.app.task,启动模式为SingleTask;A启动B后,B启动C,C再启动A后,A启动B后,点击back点击显示谁?
    分析:
    ①定义两个任务栈S1和S2
    ②A和B的TaskAffinity不同,A启动B的时候,不存在名为"com.app.task"的任务栈,所以创建一个新的任务栈S2;
    ③B启动C,他们的TaskAffinity相同,任务栈已存在,将C直接入栈,置于B的上面;
    ④C启动A,A的启动模式是standard,会在S2中入栈;
    ⑤A启动B,这时候要启动的B在S2中已经存在了,就将它上面的CA全部出栈,S2中只剩下B;
    ⑥再点Back键,B出栈,直接返回桌面,因为这时候最开始A所在的S1任务栈是后台栈;这时候后台任务栈就变成前台任务栈了,A显示,再次点击back键,返回桌面;

通过Intent标志位指定启动模式

  • 和manifest中设置有什么区别?
    manifest中无法设置Intent.FLAG_ACTIVITY_CLEAR_TOP
    Intent方式无法设置SingleInstance;

  • 常用的几个:
    ①这个和在xml中的效果是一样的,singleTop

 intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

②这个和在xml中的效果是一样的,singleTask

 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

③这个表示将上面的activity都清空出栈,一般和②搭配使用,如果要启动的activity存在,则调用onNewIntent(),清空它上面的activity;如果要启动的activity是standard模式,则它会连同它上面的activity一块清空,然后创建新的实例

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

④这个表示将要启动的activity不会添加到历史activity中,和在xml中加入android:excludeFromRecents="true"效果一样

intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);

Intent-filter匹配规则

学习笔记| (二) 组件篇之Activity启动模式_第1张图片
intent-filter匹配规则.png

你可能感兴趣的:(学习笔记| (二) 组件篇之Activity启动模式)