美文网首页
Activity的启动模式

Activity的启动模式

作者: JimmieYang | 来源:发表于2018-10-03 11:44 被阅读629次

    任务栈

    1. android任务栈又称为Task,它是一个栈结构,具有后进先出的特性,用于存放我们的Activity组件。
    2. 我们每次打开一个新的Activity或者退出当前Activity都会在一个称为任务栈的结构中添加或者减少一个Activity组件,因此一个任务栈包含了一个activity的集合, android系统可以通过Task有序地管理每个activity,并决定哪个Activity与用户进行交互:只有在任务栈栈顶的activity才可以跟用户进行交互。
    3. 在我们退出应用程序时,必须把所有的任务栈中所有的activity清除出栈时,任务栈才会被销毁。当然任务栈也可以移动到后台, 并且保留了每一个activity的状态. 可以有序的给用户列出它们的任务, 同时也不会丢失Activity的状态信息。
    4. 需要注意的是,一个App中可能不止一个任务栈,某些特殊情况下,单独一个Actvity可以独享一个任务栈。还有一点就是一个Task中的Actvity可以来自不同的App,同一个App的Activity也可能不在一个Task中。

    任务栈信息可以通过 adb shell dumpsys activity activities | sed -En -e '/Running activities/,/Run #0/p'指令来查看 栈信息.

    四种启动模式

    1. standard : 默认的启动模式,每次启动一个Activity都会重新创建一个新的实例,不管这个实例是否存在.Activity的启动三回调(onCreate()->onStart()->onResume())都会执行。 如在一个任务栈中,连续调用3次MainActivity,那么任务占中就会存在三个MainActivity记录.
    2. singTop : 栈顶复用模式. 当准备启动的Activity已经位于任务栈栈顶时,不会再创建一个新的Activity,此时栈顶Activity的 onNewIntent方法会被回调.当准备启动的Activity不在任务栈的栈顶存在时,(无论在栈中存在或者在非栈顶),都会重新创建 Activity.
    3. singleInstance : 单实例模式. 系统为声明为singleInstance模式的Activity,单独使用一个任务栈存放.即一个Activity对应一个任务栈,且一个Activity最多存在一个实例. 后续请求都不会创建Activity,只会调用其 onNewIntent回调.
    4. singleTask : 栈内复用模式. 在这种模式下,如果Activity已经存在某个任务栈中,多起启动该Activity都不会被重建,只会调用其onNewIntent方法,并将其移动到栈顶位置.

    singleTask模式

    当启动Activity时,如果Activity已经存在于 任务栈的非栈顶位置, 任务栈中该Activity之上的 Activity将会被全部移除,只保留该Activity以及其一下的Activity.
    即 具有 clearTop的效果.

    当启动Activity的任务栈B在后台时,此时任务栈A中的Activity启动了,任务栈B中的 singleTask模式的Activity,则任务B栈的 被启动Activity会clearTop到栈顶位置,然后整个任务栈B重返至前台.

    引用 官方示例来说明 :


    2018-10-02-22-46-05

    前台栈中的栈顶Activity2 启动了 位于后台栈的 ActivityY,此时 后台栈中的 ActivityY和ActivityX 都会被移动至前台栈中,回退两次才能回到 Activity2.

    taskAffinity属性

    taskAffinityAndroidManifest中 Activity标签的属性,表示任务栈的名称.该属性可以为 Activity指定任务栈.

    1. 当Activity的启动模式为 standard,singletop模式时,taskAffinity属性将失效, Activity的将被加入到 启动它的那个Activity所在的栈.一个例外,如果在入口Activity中指定 taskAffinity属性,则可以生效,因为此时应用刚启动,还没有指定的任务栈(默认的任务栈是以包名来命名的).

    2. 当Activity的启动模式为 singleTask,singleInstance模式时,taskAffinity属性将在Activity被启动的时候指定任务栈,如果任务栈不存在则会创建一个taskAffinity命名的任务栈存放启动的Activity.

    注意事项

    1. 如果被启动的Activity是 standard,singletop模式时, Activity将被加入到启动该Activity的任务栈中.

    2. 如果被启动的Activity是 singleTask,singleInstance模式时,如果指定taskAffinity属性,则Activity被加入到 指定的栈任务栈中,未指定则被加入 以包名命名的任务栈. singleInstance模式的Activity,虽然可能被加入到名字相同的栈,但是由于其特殊性,虽然栈名相同但是不属于同一个栈.

    3. 使用 application来启动Activity时, application没有所在的 任务栈.如果没有指定 FLAG_ACTIVITY_NEW_TASK,将会有如下报错.

     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中的 Flags

    1. FLAG_ACTIVITY_NEW_TASK : 为Activity指定 singleTask模式,相当于在xml中指定启动模式一样,除了application来启动Activity时,在xml指定singleTask是无效的,一定要在intent中指定该标志.
    2. FLAG_ACTIVITY_SINGLE_TOP : 指定singleTop模式.
    3. FLAG_ACTIVITY_CLEAR_TOP : 具有此标记的Activity,当它启东市,在同一个任务栈中的所有位于它上面的Activity都将被移除任务栈.
    4. FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS : 设置了该标志,该Activity所在的任务栈将不会出现在 多任务列表(最近使用列表)中.相当于设置了android:excludeFromRecents="true".

    IntentFilter匹配规则

    intent的启动有两种方式,显式调用和隐式调用.
    显示调用,我们需要明确的指定被启动的Activity的组件信息,Activity的class对象.
    隐式调用则不需要明确的知道 被调用的Activity信息,而是通过IntentFilter来指定action,category,data过滤规则配合来启动Activity.

    Intent只有同时匹配了 action规则,category规则 和 data规则,才能成功的启动目标Activity.

    一个 IntentFilter中可以设置多个 action,多个category和多个data.

    action

    intent中必须设置 action, 且能过匹配 IntentFilter中的任意一个 action就算匹配成功.

    category

    intent中如果含有 category,那么所有的category都能在IntentFilter中匹配上,intent中也可以不显式的设置category.

    在调用 startActivity或者startActivityForResult时,系统会为intent自动添加 android.intent.category.DEFAULT标志,所以如果要想隐式的调用Activity,就必须在 IntentFilter中添加 <category android:name="android.intent.category.DEFAULT" />规则.

    data

    <data android:scheme="string"
          android:host="string"
          android:port="string"
          android:path="string"
          android:pathPattern="string"
          android:pathPrefix="string"
          android:mimeType="string" />
    

    data由两部分组成, URI 和 mimeType(媒体类型).

    URI结构 : <scheme>://<host>:<port>[<path>|<pathPrefix>|<pathPattern>]
    mimeType : image/jpeg,video/*等.

    如果IntentFilter中设置了 data属性.则intent中必须设置 setData或者setType或者setDataAndType.
    setData或者setType方法的属性会相互覆盖.各自的方法会将对方属性设置为null.

    data中指设置了 mimeType时,可以使用 schemefile或content类型来设置data.
    如果需要同时指定URImimeType,需要使用intent的setDataAndType方法.

    隐式调用,可达性检查

    隐式intent启动之前,我们可以先检查 目标Activity的可达性,避免出现 android.content.ActivityNotFoundException: No Activity found to handle Intent的错误.

    使用 intent的 intent.resolveActivity(packageManager) 和 packageManager的packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY)来检查, 返回 null则表示找不到匹配的Activity.

    参考

    1. Android开发艺术探索(任玉刚)
    2. 任务和返回栈(android官方教程)

    相关文章

      网友评论

          本文标题:Activity的启动模式

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