美文网首页
浅析Activity启动模式

浅析Activity启动模式

作者: AndrLin | 来源:发表于2018-01-04 16:37 被阅读0次

    四种启动模式

    standard(默认模式)

    举个栗子
    • 同一App中默认模式下的Activity启动情况?

    下面来看个例子,Activity1 启动 Activity2,Activity2 再启动 Activity1。下面是输出的日志:

    com.demo.activity.Activity1@61b47ba
    com.demo.activity.Activity2@16908e9
    com.demo.activity.Activity1@e6cbe2
    

    根据上面的输出日志,可以知道每次创建的Activity都是一个新的实例。

    • App2启动App1中默认模式下的Activity的情况?

    先启动App1,再启动App2,App2启动App1中的Activity2:

    D/ActivityOne: com.demo.activity.Activity1@2946b4d onCreate taskId: 62
    D/ActivityTwo: com.demo.activity.Activity1@2946b4d onCreate taskId: 63
    D/ActivityOne: com.demo.activity.Activity2@1a7626a onCreate taskId: 63
    

    从日志可以看出,启动默认模式Activity,会在启动它的任务栈中创建新的实例。

    结论
    Standard默认模式

    在此模式下,每次启动Activity都会在启动它的任务栈中创建新的实例。

    singleTop(栈顶单例模式)

    举个栗子
    • 正常情况

    首先将Activity1的启动模式设置为singleTop,Activity1 启动 Activity2,Activity2 再启动 Activity1。下面是输出的日志:

    com.demo.activity.Activity1@61b47ba
    com.demo.activity.Activity2@d404aa5
    com.demo.activity.Activity1@c371793
    

    Activity2 启动 Activity1 的时候,Activity2位于栈顶,Activity1位于栈底,依然创建了新的 Activity1 实例。

    • 启动自身

    我们将 Activity2 设置为singleTop,并且在Activity2中启动它本身。下面是输出的日志:

    com.demo.activity.Activity1@6bbba71
    com.demo.activity.Activity2@34fb18c
    Activity2 onNewIntent()
    

    Activity2 启动它本身,并没有再创建新的实例,但是调用了它的onNewIntent方法。

    • 跨程序启动

    先启动App1,再启动App2,App2启动App1中的Activity2:

    D/ActivityOne: com.demo.activity.Activity1@2946b4d onCreate taskId: 64
    D/ActivityTwo: com.demo.activity.Activity1@2946b4d onCreate taskId: 65
    D/ActivityOne: com.demo.activity.Activity2@1a7626a onCreate taskId: 65
    

    再来看看App1中已经存在singleTop模式的Activity2实例情况下,App2调用会发生什么情况:

    D/ActivityOne: com.demo.activity.Activity1@2946b4d onCreate taskId: 67
    D/ActivityOne: com.demo.activity.Activity2@dcb37f8 onCreate taskId: 67
    D/ActivityTwo: com.demo.activity.Activity1@2946b4d onCreate taskId: 68
    D/ActivityOne: com.demo.activity.Activity2@ae41b40 onCreate taskId: 68
    

    根据输出日志可知,和standard模式情况一样,都会在启动它的任务栈中创建新的实例(只要启动它的任务栈栈顶不是它,都会创建新的)。

    结论
    SingleTop栈顶单例模式

    当将要启动的Activity已经位于栈顶时(已经存在,并且位于栈顶),将不会再创建实例,会调用该Activity实例的onNewIntent函数。如果Activity不在栈顶,则会和standard模式一样,创建新的实例,并放入启动它的任务栈栈顶。

    singleTask (栈内单例模式)

    举个栗子
    • 同一App内

    创建3个Activity,并将Activity2设置为singleTask。Activity1 -> Activity2 -> Activity3 -> Activity2,下面是输出日志:

    D/Activity1: com.demo.activity.Activity1@342e665c taskId: 21
    D/Activity1: onStart
    D/Activity1: onResume
    D/Activity1: onPause
    D/Activity2: com.demo.activity.Activity2@2540cea8 taskId: 21
    D/Activity2: onStart
    D/Activity2: onResume
    D/Activity1: onActivitySaveInstanceState
    D/Activity1: onStop
    D/Activity2: onPause
    D/Activity3: com.demo.activity.Activity3@38fddd69 taskId: 21
    D/Activity3: onStart
    D/Activity3: onResume
    D/Activity2: onActivitySaveInstanceState
    D/Activity2: onStop
    D/Activity3: onPause
    D/Activity2: Activity2 onNewIntent()
    D/Activity2: onStart
    D/Activity2: onResume
    D/Activity3: onStop
    D/Activity3: onDestroy
    

    当Activity3启动Activity2之后,Activity3进入了销毁生命周期,而Activity2分别调用了 onNewIntent -> onStart -> onResume,并没有创建新的Activity2实例。

    • 跨App调用

    App2启动并调用App1的Activity2(singleTask):

    D/ActivityTwo: com.demo.activity.Activity1@2946b4d onCreate taskId: 70
    D/ActivityOne: com.demo.activity.Activity2@2946b4d onCreate taskId: 71
    

    taskId不同,创建了新的栈,并在其栈底实例化新实例。

    App2和App1都启动的情况,App2调用:

    D/ActivityTwo: com.demo.activity.Activity1@2946b4d onCreate taskId: 72
    D/ActivityOne: com.demo.activity.Activity2@2946b4d onCreate taskId: 73
    D/ActivityOne: com.demo.activity.Activity2@1a7626a onCreate taskId: 73
    

    在上面基础上,再使用App2调用:

    D/ActivityOne: com.demo.activity.Activity2@1a7626a onNewIntent() taskId:73
    

    App1的Activity2并没有重新创建新实例。

    结论
    SingleTask(栈内单例模式)

    和singleTop类似,只不过singleTop是检测栈顶元素是否是需要启动的Activity,而singleTask是检测整个栈中是否存在当前需要启动的Activity。如果存在,则将该Activity以上的Activity退栈销毁,让该Activity置顶,也会触发onNewIntent。

    以上指的是同一APP中启动singleTask的Activity,如果是其他程序以singleTask模式来启动该Activity,会创建一个新的任务栈。如果启动模式为singleTask的Activity已经在后台一个任务栈中存在,那么启动后,后台的这个任务栈将一起被切换到前台。

    值得注意的是:singleTask模式启动的Activity所存在的任务栈,可以由<activity>的参数taskAffinity来设置。点击查看(处理关联)

    singleInstance(全局单例模式)

    举个栗子
    • 将Activity2设置为singleInstance,启动Activity1,Activity1再启动Activity2:
    D/ActivityOne: com.demo.activity.Activity1@2946b4d onCreate taskId: 83
    D/ActivityOne: com.demo.activity.Activity2@177dba4 onCreate taskId: 84
    
    • 使用App2调用已经启动的上述Activity2:
    D/ActivityTwo: com.demo.activity.Activity1@2946b4d onCreate taskId: 88
    D/ActivityOne: com.demo.activity.Activity2@177dba4 onNewIntent() taskId: 84
    
    结论
    SingleInstance(全局单例模式)

    该模式的Activity会在一个独立的任务栈中开启,并且这个任务栈中有且仅有这一个实例。当再次启动该Activity时,会重用已存在的任务栈和实例,并且会调用该实例的onNewIntent函数。同一时刻在系统中只会存在一个这样的Activity实例。

    Intent Flags

    除了在清单文件中配置launchMode来设置启动模式外,还可以在使用startActivity时给Intent设置相应的Flag,来达到相应的效果。

    • FLAG_ACTIVITY_NEW_TASK

    使用一个新的Task来启动Activity,如果已有正在启动Activity的运行任务,则该任务会转到前台并恢复其最后状态,同时Activity会在onNewIntent()中收到新Intent。与"singleTask"launchMode是一样的。

    • FLAG_ACTIVITY_SINGLE_TOP

    和singleTop效果相同。

    • FLAG_ACTIVITY_CLEAR_TOP

    如果正在启动的 Activity 已在当前任务中运行,则会销毁当前任务顶部的所有 Activity,并调用onNewIntent传递Intent,不会创建新实例。

    FLAG_ACTIVITY_CLEAR_TOP通常与FLAG_ACTIVITY_NEW_TASK结合使用。一起使用时,通过这些标志,可以找到其他任务中的现有 Activity,并将其放入可从中响应 Intent的位置。

    :如果指定 Activity 的启动模式为"standard",则该 Activity 也会从堆栈中移除,并在其位置启动一个新实例,以便处理传入的 Intent。这是因为当启动模式为"standard"时,将始终为新 Intent 创建新实例。

    • FLAG_ACTIVITY_NO_HISTORY

    当该模式启动的ActivityA再启动ActivityB后,ActivityA就消失了,不会保留在Activity栈中。

    参考文案

    《Android开发艺术探索》—— 任玉刚

    官方文档

    相关文章

      网友评论

          本文标题:浅析Activity启动模式

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