美文网首页生活程序员
学习笔记| (二) 组件篇之Activity启动模式

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

作者: yanerly | 来源:发表于2018-09-22 01:03 被阅读34次

    一.启动模式:

    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"一起使用
    <activity
                android:name=".BActivity"
                android:launchMode="singleTask"
                android:taskAffinity="com.app.b"/>
    

    也就是所有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匹配规则

    intent-filter匹配规则.png

    相关文章

      网友评论

        本文标题:学习笔记| (二) 组件篇之Activity启动模式

        本文链接:https://www.haomeiwen.com/subject/rlhznftx.html