美文网首页Android面试知识
Activity(三)栈管理

Activity(三)栈管理

作者: 风风风筝 | 来源:发表于2016-09-03 10:03 被阅读1976次

    一、主要涉及4个类

    1) ActivityRecord
    源码注释:An entry in the history stack, representing an activity.
    翻译一下:存在历史栈的一个实例,代表一个Activity。
    2) TaskRecord
    Activity栈,内部维护一个ArrayList<ActivityRecord>
    3) ActivityStack
    并不是一个Activity栈,真正意义上的Activity栈是TaskRecord,这个类是负责管理各个Activity栈,内部维护一个ArrayList<TaskRecord>
    4) ActivityStackSupervisor
    内部持有一个ActivityStack,而ActivityStack内部也持有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里构造一个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);
      }

    2. 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模式不会创建新的TaskRecord
    构造一个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为空时,会触发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调用startActivity,那么目标Activity就不知道自己该属于哪个TaskRecord,所以得指定FLAG_ACTIVITY_NEW_TASK,就会新建一个TaskRecord

    相关文章

      网友评论

      • hurtsogood:楼主这些Log是怎么打出来的,在桌面上点击一个应用,直接在Android studio里面能看吗 我怎么看不见 小白求指教
        风风风筝:还有最基本的:手机系统必须是原生的,简单点就用模拟器吧
        风风风筝:@hurtsogood 点击开始调试的时候弹出 Choose Process 对话框,要勾选 Show all processes 然后选择 system_process
      • 捡淑:马克

      本文标题:Activity(三)栈管理

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