Activity(三)棧管理

一、主要涉及4個類

1) ActivityRecord
源碼注釋:An entry in the history stack, representing an activity.
翻譯一下:存在歷史棧的一個實例,代表一個Activity。
2) TaskRecord
Activity棧,內(nèi)部維護一個ArrayList<ActivityRecord>
3) ActivityStack
并不是一個Activity棧,真正意義上的Activity棧是TaskRecord,這個類是負責(zé)管理各個Activity棧,內(nèi)部維護一個ArrayList<TaskRecord>
4) ActivityStackSupervisor
內(nèi)部持有一個ActivityStack,而ActivityStack內(nèi)部也持有ActivityStackSupervisor,相當于ActivityStack的輔助管理類

ActivityRecord
final class ActivityRecord {
    TaskRecord task;  // the task this is in.
    final IApplicationToken.Stub appToken;
    final int userId;
    int theme;
    int launchMode;
    ...
}

成員變量task表示自己所在的TaskRecord,這樣要找到自己所在的TaskRecord就不必遍歷查找了。

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

    /** Current stack */
    ActivityStack stack;
}

同樣的道理,成員變量stack表示自己所在的ActivityStack

ActivityStack
final class ActivityStack {
    private ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();

    /** Run all ActivityStacks through this */
    final ActivityStackSupervisor mStackSupervisor;

    ActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer, RecentTasks recentTasks) {
        mStackSupervisor = activityContainer.getOuter();
        ...
    }
}
ActivityStackSupervisor
public final class ActivityStackSupervisor {
    private ActivityStack mFocusedStack;
}

二、場景解析

1、從桌面第一次啟動App

startActivityLocked里構(gòu)造一個ActivityRecord
新建一個TaskRecord,并存入mTaskHistory
ActivityRecord存入mActivities

final int startActivityUncheckedLocked(...) {
    final int startActivityUncheckedLocked(...) {
    if (reuseTask == null) {
        r.setTask(targetStack.createTaskRecord(...);
        ...
        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
        ...
    }
}
  1. TaskRecord存入mTaskHistory
 TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            boolean toTop) {
        TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession,
                voiceInteractor);
        addTask(task, toTop, false);
        return task;
    }

    void addTask(final TaskRecord task, final boolean toTop, boolean moving) {
        task.stack = this;
        if (toTop) {
            insertTaskAtTop(task, null);
        } else {
            mTaskHistory.add(0, task);
            updateTaskMovement(task, false);
        }
        ...
    }

    private void insertTaskAtTop(TaskRecord task, ActivityRecord newActivity) {
        ...
        mTaskHistory.add(taskNdx, task);
        updateTaskMovement(task, true);
    }
  1. ActivityRecord存入mActivities
final void startActivityLocked(ActivityRecord r, boolean newTask, ...) {
    ...
    task = mTaskHistory.get(taskNdx);
    ...
    task.addActivityToTop(r);
}
void addActivityToTop(ActivityRecord r) {
    addActivityAtIndex(mActivities.size(), r);
}
void addActivityAtIndex(int index, ActivityRecord r) {
    ...
    mActivities.add(index, r);
    ...
}
2、App啟動一個Activity

會不會新建一個TaskRecord取決于launchMode,默認的standard模式不會創(chuàng)建新的TaskRecord
構(gòu)造一個ActivityRecord存入mActivities,與上面第二步一樣

3、回退
/** @return true if this was the last activity in the task */
boolean removeActivity(ActivityRecord r) {
    mActivities.remove(r);
    ...
    if (mActivities.isEmpty()) {
        return !mReuseTask;
    }
    ...
    return false;
}

4、再次回退,回到桌面

從mActivities移除當前ActivityRecord與上面一樣,只是當mActivities為空時,會觸發(fā)mTaskHistory移除當前TaskRecord,如果mTaskHistory為空,則切換到桌面,給mStackSupervisor.mFocusedStack重新賦值

private void removeActivityFromHistoryLocked(ActivityRecord r, String reason) {
    ...
    final TaskRecord task = r.task;
    if (task != null && task.removeActivity(r)) {
        if (mStackSupervisor.isFrontStack(this) && task == topTask() &&
                task.isOverHomeStack()) {
            mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(), reason);
        }
        removeTask(task, reason);
    }
}

void removeTask(TaskRecord task, String reason, boolean notMoving) {
    ...
    mTaskHistory.remove(task);
    ...
    if (mTaskHistory.isEmpty()) {
        final boolean notHomeStack = !isHomeStack();
        if (isOnHomeDisplay()) {
            String myReason = reason + " leftTaskHistoryEmpty";
            if (mFullscreen || !adjustFocusToNextVisibleStackLocked(null, myReason)) {
                mStackSupervisor.moveHomeStack(notHomeStack, myReason);
            }
        }
        ...
    }
    ...
    task.stack = null;
}

如果不是從Activity調(diào)用startActivity,那么目標Activity就不知道自己該屬于哪個TaskRecord,所以得指定FLAG_ACTIVITY_NEW_TASK,就會新建一個TaskRecord

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 個人總結(jié): 一個應(yīng)用程序只有一個任務(wù)棧(Stack); 一個應(yīng)用程序可以有多個Task(一個Task表現(xiàn)于回退棧,...
    畫十閱讀 1,878評論 0 3
  • 簡介: 在android系統(tǒng)中,Home界面也就是Launcher的界面,Launcher它本身也是一個應(yīng)用程序,...
    Memebox閱讀 2,670評論 4 19
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,094評論 25 709
  • 看看日歷,我們的生日又到了,只是:你我變成了爺奶,他她變成了姥爺和姥姥;只是:你我變成了旅游俠,他她變成了顧問和編...
    更新亂語閱讀 175評論 0 0
  • 注:本文將從影片的色彩基調(diào):“紅與藍”,以及它們所象征的“愛與悲”記錄觀影感受。 曾經(jīng),未見大魚,就對它產(chǎn)生了無限...
    dk萍萍閱讀 14,121評論 134 172

友情鏈接更多精彩內(nèi)容