Activity启动模式笔记

170 阅读4分钟

参考资料:

在聊四种启动模式之前,先了解一下taskAffinity(任务相关性)属性

taskAffinity属性:

每个Activity都有一个taskAffinity,可以自定义,默认与所在Application的taskAffinity相同,Application的taskAffinity默认取自App包名

每个Task都有其taskAffinity,值取自栈底的Activity的taskAffinity

taskAffiniy相当于会对Activity进行分组,也相当于给每个Task起一个id值,最近任务列表相同的taskAffiniy的Task只会显示一个

回退栈:

我们知道每个Task都有一个Activity的回退栈,但其实不光Activity能堆叠成栈,Task也能堆叠在一起

standard:

默认情况下,Activity会直接进入当前Task,为一个Activity创建多个实例,进入不同的Task

singleTask:

启动设置singleTask的Activity实例时,系统会比较Activity和当前Task的taskAffinity是否相同

  • 相同则直接入栈
  • 不同
    • 先查找是否存在以及启动的相同的Task,入栈,并将这个Task堆叠到当前Task上面
    • 如果没有,则会创建一个新的Task

Task堆叠只适用于前台Task,当Task从前台切到后台,不同Task会分开,前台进入后台场景:

  • Home键回到桌面
  • 按最近任务键查看最近任务(查看时便已经切到后台,而不是在应用切换时)

还可以保证同一个Task中只会有一个这个Activity实例,当前Task中有这个Activity实例时,会复用,不会调用onCreate()而是调用其onNewIntent(),其上面的Activity会被全部清掉

singleTask保证了只有一个Task中有这个Activity,也保证了这个Task中只有一个这个Activity,限制这个Activity全局只有一个对象

allowTaskReparenting属性:

Activity默认情况下只会归属于一个Task,不会在Task之间移动

而设置属性android:allowTaskReparenting="true"时,A启动B的Activity时,Activity实例会进入A的Task,再打开B时,Activity实例会移动到B的Task中顶端,再回到A中时Activity实例不见了

好处:

  • 相较于singleTask,启动Activity时,还是在一个Task中创建,所以入场动画不会是Task切换动画,而是普通Activity入场动画
  • Task从切到后台再切回来时,不是像singleTask切断自己的回退路径

注意:Android 9以及Android 10上该属性不适用

singleInstance:

行为逻辑与singleTask基本一致,多了一个更严格的限制这个Task里只有这么一个Activity(独占一个Task)

singleTask强调唯一性,singleIstance还强调独占性

由于taskAffinity的限制,当用户退回桌面点击Activity所在的App时,singleTask会看到这个Activity依然在栈顶,而singleInstance会看到这个Activity并不见了(切到了后台,当有App使用它时,会调用其onNewIntent()启动它)

singleTop:

和standard一样,启动时不考虑taskAffinity,区别在于会重用栈顶的Activity,调用其onNewIntent()

实际使用:

  • standard和singleTop:多用于App内部
  • singleInstance:多用于开放给外部App来共享使用
  • singleTask:内部交互和外部交互都可以用到

总结一下: 有四种启动模式standard、singleTask、singleTop和singleInstance,首先说standard,标准启动模式对于启动一个新Activity,无论这个是不是跨应用的Activity,都会将实例放在当前的Task中。singleTop基本与standard一样,不同在于如果当前栈顶的Activity是要启动的Activity,则调用其onNewIntent()方法复用这个Activity。singleTask可以分为这几种情况说一下,首先如果要启动的Activity与当前Task的taskAffinity相同的话,则会先查找这个task中是否已经有这个Activity实例,如果有,则将其上面的所有Activity出栈使其到栈顶,如果没有则新创建实例入栈;如果启动的Activity与当前的Task的taskAffiniy不同,则会先去找是否有启动的相同taskAffinity的Task,如果有,则进入那个任务栈,然后将那个Task压在当前Task上面,如果没有则新创建一个Task,入栈,将这个Task压在当前Task上面。singleInstance与singleTask基本一致,但更严格的地方在于,singleInstance要求,启动的这个Activity是独占一个Task