Activity--LaunchMode启动模式(2)

一、为什么需要启动模式

默认情况下,当我们多次启动同一个activity的时候,系统会创建多个实例并把它们一一放入任务栈中,当点击back按键的时候,把栈中的activity一一回退。任务栈是“后进先出”的结构。这样会照成同一个activity重复创建多个实例,因此activity设计了四种启动模式来修改系统的默认行为。

二、Activity的四种启动方式

1、standard:标准模式

系统默认的启动方式,每次启动一个activity都会重新创建一个新的实例,不管这个实例是否已经存在。被重新创建的activity都会调用onCreate、onStart、onResume方法。这个模式下,一个任务栈中可以有多个实例。这种模式下,谁启动这个activity,那么这个activity就运行在启动它的任务栈中。比如A activity启动B activity(standard模式),那么B activity就运行在A activity的任务栈中。
由此可见如果用非activity的content去启动standard模式的activity就会报错,如Application的cantent去调用startActivity()方法,就会报错,是因为application没有自己的任务栈。

2、singleTop:栈顶复用模式

在这种模式下,如果新activity已经位于任务栈的栈顶,那么此activity不会被重复创建,同时它的onNewIntent方法会被回调,同个此方法的参数我们可以取出当前请求的信息。这时这个activity的onCreate、onStart和onResume方法不会被系统调用。如果新activity的实例已经存在但是不位于栈顶,那么新的activity任然会被重新创建,系统会调用onCreate、onStart和onResume方法。

举个例子:栈内存在ABCD四个activity,A位于栈底,D位于栈顶
再次启动D,D的启动模式为singleTop,栈内的情况仍为ABCD
再次启动B,B的启动模式为singleTop,栈内的情况为ABCDB
再次启动D,D的启动模式为standard,栈内的情况为ABCDBD


给activity设置启动模式
1、在AndroidMenifest.xml中设置启动方式


            
                

                
            
        

2、在intent中设置标志位为activity设置启动模式

var intent = Intent(this,SecondActivity::class.java)
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            startActivity(intent)

3、singleTask:栈内复用模式

这是一种单实例模式,在这种模式下,只要Activity在一个栈内存在,那么多次启动此activity都不会重新创建实例,和singleTop一样,系统会调用onNewIntent。具体一点就是当1activity(singleTask模式)被启动时,系统会在寻找是否存在A activity所需要的任务栈,如果不存在会创建一个A activity 需要的任务栈,并把A activity压入任务栈,如果存在A activity需要的任务栈,那么就会查找任务栈中是否有A activity的实例,如果存在,就会A activity调到栈顶,调用onNewIntent方法,并把A activity上面的activity清出栈。如果不存在创建A activity的实例,并压入栈。

举个例子D activity需要启动,D activity的启动模式是singleTask模式,需要任务栈T1
任务栈T1中有ABC三个activity,这时启动D,D会被压入T1中,T1中有ABCD四个activity
任务栈T1再次启动A(singleTask模式),调用A的onNewIntent方法,这时BCD会弹出栈,栈中只有A一个activity
任务栈T2中有ABC三个activity,这时启动D,系统会先创建任务栈T1,并把D压入T1中

4、singleInstance:单实例模式

这是一种加强的singleTask模式,它除了具有singleTask的所有特性外,还加强了一点,那就是具有此种模式下的activity只能单独位于一个任务栈中。这个任务栈中只有一个activity,由于栈内复用的特性,后续的请求都不会创建新的activity,除非这个独特的任务栈被系统销毁。

三、举个特殊情况的例子

现在有两个任务栈,一个前台任务栈中有AB两个activity,另一个后台任务栈有CD两个activity,并且CD两个activity的启动方式都为singleTask。

情景1、在B中启动D,那么整个后退列表就变成了ABCD,用户点击back按钮,D弹出,再次点击back,C弹出,再次点击back,B弹出。
情景2、在B中启动C,那么整个后退列表就变成ABC,用户点击back按钮,C弹出,再次点击back,B弹出

四、TaskAffinity

TaskAffinity可以翻译成任务相关性,这个参数标识了一个activity所需要的的任务栈的名称,默认情况下所有activity的任务栈的名称为应用的包名。当然,我们可以为每个activity单独指定一个TaskAffinity属性,这个属性必须不能和包名相同,否则就没有意义了。
TaskAffinity的设置在AndroidMenifest.xml中


    
        

查看任务栈的方法

adb shell dumpsys activity
//日志很多直接查询Running activities(most recent first)这一块
6587b35543dd376d3bb84ed8e0bed32.png

TaskAffinity属性主要和singleTask启动模式或者allowTaskReparenting属性配合使用。
另外任务栈分为前台任务栈和后台任务栈,后台任务栈中的activity处于暂停状态,用户可以通过切换将后台任务栈掉到前台。
1、当TaskAffinity和singleTask配合使用的时候,具有该模式的activity会运行在名称和TaskAffinity相同的任务栈中。
2、android:allowTaskReparenting的主要作用是activity的迁移,即从一个task迁移到另一个task,这个迁移跟activity的taskAffinity有关,必须是从一个跟该activity taskAffinity不同的task中迁移到跟它taskAffinity相同的task中。



举个例子:
①AB两个activity,启动模式为standard,任务栈为com.yusong.study(包名),CD两个activity,启动模式为singleTask,且TaskAffinity为com.yusong.task,启动顺序为A中启动B,B中启动C,C中启动D


        
        
        
            
                

                
            
        

启动应用,通过adb shell dumpsys activity,查看任务栈


2679b49bfbf11aa95e730b7b646ab04.png

78c474a90d0a543bd4168c4aef3c777.png

通过日志我们能看到有两个任务栈,分别为com.yusong.study和com.yusong.task,并且每个任务栈有两个activity

你可能感兴趣的:(Activity--LaunchMode启动模式(2))