AMS源码分析--finish()源码分析2

622 阅读2分钟

前言

源码分析基于android-26

案例

  1. 在MainActivity中通过startActivityForResult()方法启动AActivity
Intent intent = new Intent(MainActivity.this, AActivity.class);
startActivityForResult(intent,1);

2.AActivity启动BActivity后,finish掉

findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(AActivity.this, BActivity.class);
        startActivity(intent);
        setResult(Activity.RESULT_OK);
        finish();
    }
});

3.BActivity通过back按键

讨论

这个案例和前文的案例的区别是:AActivity在启动BActivity的同时finish掉了自己。

源码

1.AActivity的finish流程如下

1.Activity#finish(DONT_FINISH_TASK_WITH_ACTIVITY)
2.ActivityManagerService#finishActivity
3.ActivityStack#requestFinishActivityLocked
4.ActivityStack#finishActivityLocked
5.ActivityStack#startPausingLocked;
6.prev.app.thread.schedulePauseActivity;
7.ActivityStack#schedulePauseTimeout
7.ActivityThread#handlePauseActivity
8.ActivityManagerService#activityPaused
9.ActivityStack#activityPausedLocked
9.ActivityStack#completePauseLocked
10.ActivityStack#finishCurrentActivityLocked
11.ActivityStackSupervisor#resumeFocusedStackTopActivityLocked;
12.ActivityStackSupervisor#resumeTopActivityUncheckedLocked;

2.在看下resumeTopActivityUncheckedLocked方法

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    // Find the next top-most activity to resume in this stack that is not finishing and is
    // focusable. If it is not focusable, we will fall into the case below to resume the
    // top activity in the next focusable task.
    //  找到顶部的Activity,此时是BActivity
    final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
    // 省略部分代码
    // If the top activity is the resumed one, nothing to do.
    // mResumedActivity就是BActivity,并且其 == ActivityState.RESUMED
    if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
                mStackSupervisor.allResumedActivitiesComplete()) {
        // Make sure we have executed any pending transitions, since there
        // should be nothing left to do at this point.
        executeAppTransition(options);
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Top activity resumed " + next);
        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        // 直接return掉
        return false;
    }

3.可以看到resumeTopActivityInnerLocked直接return掉了

4.从BActivity点击back返回到MainActivity的逻辑和前文一致,唯一需要注意的点是:在AActivityfinish掉的时候已经为MainActivity的results进行了赋值,代码如下

ActivityStack#finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
            String reason, boolean oomAdj, boolean pauseImmediately){
    // 省略部分代码..
    
    finishActivityResultsLocked(r, resultCode, resultData);
    
    // 省略部分代码..
}

private void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
        // send the result
    ActivityRecord resultTo = r.resultTo;
    if (resultTo != null) {
        if (resultTo.userId != r.userId) {
            if (resultData != null) {
                resultData.prepareToLeaveUser(r.userId);
            }
        }
        if (r.info.applicationInfo.uid > 0) {
            mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
                    resultTo.packageName, resultData,
                    resultTo.getUriPermissionsLocked(), resultTo.userId);
        }
        resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
                                 resultData);
        r.resultTo = null;
    }
    else if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "No result destination from " + r);
    
    // Make sure this HistoryRecord is not holding on to other resources,
    // because clients have remote IPC references to this object so we
    // can't assume that will go away and want to avoid circular IPC refs.
    r.results = null;
    r.pendingResults = null;
    r.newIntents = null;
    r.icicle = null;
}

5.BActivity开始finish时,从重新找下一个栈顶的activity,此时就是MainActivity,并执行onActivityResult和performResume方法

外传

mResumedActivity到底是啥,我们看下那边赋值的

ActivityStackSupervisor#realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig){
    // 如果pause没有完成,进入下面分支,直接return
    if (!allPausedActivitiesComplete()) {
            // While there are activities pausing we skipping starting any new activities until
            // pauses are complete. NOTE: that we also do this for activities that are starting in
            // the paused state because they will first be resumed then paused on the client side.
            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                    "realStartActivityLocked: Skipping start of r=" + r
                    + " some activities pausing...");
            return false;
        }
    // 省略部分代码
    // 启动activity
    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
    System.identityHashCode(r), r.info,
    // TODO: Have this take the merged configuration instead of separate global and
    // override configs.
    mergedConfiguration.getGlobalConfiguration(),
    mergedConfiguration.getOverrideConfiguration(), r.compat,
    r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
    r.persistentState, results, newIntents, !andResume,
    mService.isNextTransitionForward(), profilerInfo);
                    
                    
    if (andResume) {
        // As part of the process of launching, ActivityThread also performs
        // a resume.
        stack.minimalResumeActivityLocked(r);
    }
}

ActivityStack#setResumedActivityLocked(ActivityRecord r, String reason) {
        // TODO: move mResumedActivity to stack supervisor,
        // there should only be 1 global copy of resumed activity.
        // 对mResumedActivity赋值
        mResumedActivity = r;
        // 赋值state
        r.state = ActivityState.RESUMED;
        mService.setResumedActivityUncheckLocked(r, reason);
        final TaskRecord task = r.getTask();
        task.touchActiveTime();
        mRecentTasks.addLocked(task);
}

可见在pause完成后,mResumedActivity就是待启动的Activity