美文网首页
2020-03-14-Activity任务栈

2020-03-14-Activity任务栈

作者: 耿望 | 来源:发表于2020-03-15 19:52 被阅读0次

有了任务栈,应用就可以复用本身的Activity,或者是使用其他应用的Activity。
我们先看一下整体的类图,主要是有三个类,ActivityStack,ActivityRecord和TaskRecord。


Activity栈管理 (1).jpg

ActivityStack

ActivityStatck用来管理Activity的任务栈,它的内部有一个枚举类型,记录Activity的状态。

    enum ActivityState {
        INITIALIZING,
        RESUMED,
        PAUSING,
        PAUSED,
        STOPPING,
        STOPPED,
        FINISHING,
        DESTROYING,
        DESTROYED,
        RESTARTING_PROCESS
    }

同时有多个ArrayList,用来存储不同类型的ActivityRecord或TaskRecord列表。

    /**
     * The back history of all previous (and possibly still
     * running) activities.  It contains #TaskRecord objects.
     */
    private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
    /**
     * List of running activities, sorted by recent usage.
     * The first entry in the list is the least recently used.
     * It contains HistoryRecord objects.
     */
    private final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();

TaskRecord

TaskRecord表示Activity的任务栈,用来记录Activity所在任务栈的所有信息,同时它的内部有一个或多个ActivityRecord。

    /** List of all activities in the task arranged in history order */
    final ArrayList<ActivityRecord> mActivities;

    /** Current stack. Setter must always be used to update the value. */
    private ActivityStack mStack;

    final int taskId;       // Unique identifier for this task.

ActivityRecord

最小的结构单位是ActivityRecord,前面介绍Activity的启动过程中,提到startActivity的时候会创建一个ActivityRecord对象,记录Activity的所有信息,主要的内容如下:

    final ActivityInfo info; // all about me
    // TODO: This is duplicated state already contained in info.applicationInfo - remove
    ApplicationInfo appInfo; // information about activity's app
    //……
    private TaskRecord task;        // the task this is in.

Launch Mode

我们通过Intent启动Activity的时候,通常要指定启动方式。

  1. standard
    默认模式,每次启动Activity都会创建一个新的Activity实例。
  2. singleTop
    如果Activity已经在栈顶,就不会创建新的Activity实例,而是调用原有Activity的onNewIntent方法,否则创建新的Activity实例。
  3. singleTask
    如果Activity已经在归属的栈中,就将该栈中Activity上的所有其他Activity出栈,同时调用它的onNewIntent方法;
    如果归属的栈中没有Activity,就创建新的实例,入栈;
    如果栈不存在,就创建新的任务栈,创建新的Activity实例,入栈。
    有些博客认为singleTask一定会创建新的任务栈,其实是不对的。正常的流程应该是:
    (1)启动activity时发现启动模式为singleTask,那么设定它的启动标志为FLAG_ACTIVITY_NEW_TASK;
    (2)获得它的taskAffinity
    (3)检查是否已经存在一个affinity相同的任务
    (4)如果任务栈存在,判断栈中是否存在该activity,将该activity上面的实例出栈,调用它的onNewIntent方法
    (5)如果activity不存在,就创建实例,入栈
    (6)如果任务栈不存在,就创建任务栈和实例
  4. singleInstance
    每次启动Activity确保栈中只有一个Activity实例。
    简单理解一下,
    standard是每次都会创建新的Activity实例,但是会跟之前保持同一个栈;
    singleTop是当Activity已经在栈顶,就不会创建新的实例,而是调用onNewIntent方法;
    singleTask是当Activity已经存在栈中,不管是否在栈顶,都调用onNewIntent方法,不会创建新的实例,并且会将该Activity之前的Activity都出栈;
    singleInstance是确保栈中只有一个Activity实例,如果栈不存在就创建新的栈,如果该栈存在,则调用onNewIntent方法。
    我们通过adb命令看一下
adb shell dumpsys activity activities
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):

  Stack #16: type=standard mode=fullscreen
  isSleeping=false
  mBounds=Rect(0, 0 - 0, 0)
    Task id #1958
    //……
    Running activities (most recent first):
      TaskRecord{4a3f612 #1958 A=com.example.zgone.calculator U=0 StackId=16 sz=3 mode=1}
        Run #2: ActivityRecord{54b2a75 u0 com.example.zgone.calculator/.MainActivity t1958}
        Run #1: ActivityRecord{cb68a4d u0 com.example.zgone.calculator/.SecondActivity t1958}
        Run #0: ActivityRecord{5102efd u0 com.example.zgone.calculator/.MainActivity t1958}

    mResumedActivity: ActivityRecord{54b2a75 u0 com.example.zgone.calculator/.MainActivity t1958}
    mLastPausedActivity: ActivityRecord{cb68a4d u0 com.example.zgone.calculator/.SecondActivity t1958}

该任务栈有三个ActivityRecord,栈顶是MainActivity。

Intent的Flag

除了在AndroidManifest中指定Launch Mode,也可以在start Activity的时候指定Intent的Flag。
1.FLAG_ACTIVITY_NEW_TASK
很多博客说这个标志跟singleTask是一样的效果,需要创建新的栈,但实际上只有在两个应用间切换的时候才是这样,如果是同个应用内部,因为taskAffinity相同,效果类似standard。
这个标志更常用的场景应该是在service中启动Activity的时候,如果使用的Context不是Activity的Context,就需要指定FLAG_ACTIVITY_NEW_TASK,否则将会出现异常crash。因为默认的启动模式是standard,这种模式会将Activity归入当前所在的任务栈,而Application Context或者Service的context是不包含任务栈的。
2.FLAG_ACTIVITY_SINGLE_TOP
功能类似singleTop
3.FLAG_ACTIVITY_CLEAR_TOP
功能类似singleTask,会将该目标Activity之前的Activity都出栈,区别是它并不是调用onNewIntent方法,而是oCreate。

taskAffinity

因为默认情况下,一个Android应用所有Activity都有一样的taskAffinity,所以这个地方容易被忽略。比如之前的FLAG_ACTIVITY_NEW_TASK,只有在两个Activity的taskAffinity不一致的情况下,才会创建新的栈。
也就是说,taskAffinity需要配合NEW_TASK标志使用才能生效。

参考

https://www.jianshu.com/p/94816e52cd77
https://blog.csdn.net/zhangjg_blog/article/details/10923643

相关文章

网友评论

      本文标题:2020-03-14-Activity任务栈

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