美文网首页Android开发经验谈Android开发程序员
终结篇:Android startActivity原理分析(基于

终结篇:Android startActivity原理分析(基于

作者: Android征途 | 来源:发表于2019-03-22 19:36 被阅读10次

    上:https://www.jianshu.com/p/76a98a341bcd上部分:Android startActivity原理分析(基于Android 8.1 AOSP)
    中:https://www.jianshu.com/p/18951d629864中部分:Android startActivity原理分析(基于Android 8.1 AOSP)

    继上文两篇后直接挂代码

    转交给了另外一个函数去处理后,我们现在往下看

    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
            if (!mService.mBooting && !mService.mBooted) {
                // Not ready yet!
                return false;
            }
    
            // 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
            // 我们的TestActivity已经入栈了,所以next就是我们的TestActivity了
            final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
    
            final boolean hasRunningActivity = next != null;
    
            // TODO: Maybe this entire condition can get removed?
            if (hasRunningActivity && getDisplay() == null) {
                return false;
            }
    
            mStackSupervisor.cancelInitializingActivities();
    
            // Remember how we'll process this pause/resume situation, and ensure
            // that the state is reset however we wind up proceeding.
            final boolean userLeaving = mStackSupervisor.mUserLeaving;
            mStackSupervisor.mUserLeaving = false;
    
            if (!hasRunningActivity) {
                // There are no activities left in the stack, let's look somewhere else.
                return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
            }
    
            next.delayedResume = false;
    
            // 如果我们要跳转的页面已经是resume状态,那么直接通知Wms执行Activity的过渡
            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 false;
            }
    
            final TaskRecord nextTask = next.getTask();
            final TaskRecord prevTask = prev != null ? prev.getTask() : null;
            if (prevTask != null && prevTask.getStack() == this &&
                    prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
                if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();
                if (prevTask == nextTask) {
                    prevTask.setFrontOfTask();
                } else if (prevTask != topTask()) {
                    // This task is going away but it was supposed to return to the home stack.
                    // Now the task above it has to return to the home task instead.
                    final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
                    mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
                } else if (!isOnHomeDisplay()) {
                    return false;
                } else if (!isHomeStack()){
                    if (DEBUG_STATES) Slog.d(TAG_STATES,
                            "resumeTopActivityLocked: Launching home next");
                    return isOnHomeDisplay() &&
                            mStackSupervisor.resumeHomeStackTask(prev, "prevFinished");
                }
            }
    
            // 判断一下是否已经进入睡眠状态,如果进入睡眠状态Activity也会进入Pause状态
            if (shouldSleepOrShutDownActivities()
                    && mLastPausedActivity == next
                    && mStackSupervisor.allPausedActivitiesComplete()) {
                // 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: Going to sleep and all paused");
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return false;
            }
    
            // Make sure that the user who owns this activity is started.  If not,
            // we will just leave it as is because someone should be bringing
            // another user's activities to the top of the stack.
            if (!mService.mUserController.hasStartedUserState(next.userId)) {
                Slog.w(TAG, "Skipping resume of top activity " + next
                        + ": user " + next.userId + " is stopped");
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return false;
            }
    
            // The activity may be waiting for stop, but that is no longer
            // appropriate for it.
            mStackSupervisor.mStoppingActivities.remove(next);
            mStackSupervisor.mGoingToSleepActivities.remove(next);
            next.sleeping = false;
            mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next);
    
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
    
            // If we are currently pausing an activity, then don't do anything until that is done.
            if (!mStackSupervisor.allPausedActivitiesComplete()) {
                if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                        "resumeTopActivityLocked: Skip resume: some activity pausing.");
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return false;
            }
    
            mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
    
            boolean lastResumedCanPip = false;
            final ActivityStack lastFocusedStack = mStackSupervisor.getLastStack();
            if (lastFocusedStack != null && lastFocusedStack != this) {
                // So, why aren't we using prev here??? See the param comment on the method. prev doesn't
                // represent the last resumed activity. However, the last focus stack does if it isn't null.
                final ActivityRecord lastResumed = lastFocusedStack.mResumedActivity;
                lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState(
                        "resumeTopActivity", userLeaving /* beforeStopping */);
            }
            // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
            // to be paused, while at the same time resuming the new resume activity only if the
            // previous activity can't go into Pip since we want to give Pip activities a chance to
            // enter Pip before resuming the next activity.
            final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
                    && !lastResumedCanPip;
            //将发起者置入Pause状态,也就是MainActivity改成onPause状态
            boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
            if (mResumedActivity != null) {
                if (DEBUG_STATES) Slog.d(TAG_STATES,
                        "resumeTopActivityLocked: Pausing " + mResumedActivity);
                pausing |= startPausingLocked(userLeaving, false, next, false);
            }
            if (pausing && !resumeWhilePausing) {
                if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
                        "resumeTopActivityLocked: Skip resume: need to start pausing");
                // At this point we want to put the upcoming activity's process
                // at the top of the LRU list, since we know we will be needing it
                // very soon and it would be a waste to let it get killed if it
                // happens to be sitting towards the end.
                if (next.app != null && next.app.thread != null) {
                    mService.updateLruProcessLocked(next.app, true, null);
                }
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return true;
            } else if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
                    mStackSupervisor.allResumedActivitiesComplete()) {
                // It is possible for the activity to be resumed when we paused back stacks above if the
                // next activity doesn't have to wait for pause to complete.
                // So, nothing else to-do except:
                // 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 (dontWaitForPause) " + next);
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return true;
            }
    
            // If the most recent activity was noHistory but was only stopped rather
            // than stopped+finished because the device went to sleep, we need to make
            // sure to finish it as we're making a new activity topmost.
            if (shouldSleepActivities() && mLastNoHistoryActivity != null &&
                    !mLastNoHistoryActivity.finishing) {
                if (DEBUG_STATES) Slog.d(TAG_STATES,
                        "no-history finish of " + mLastNoHistoryActivity + " on new resume");
                requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
                        null, "resume-no-history", false);
                mLastNoHistoryActivity = null;
            }
    
            if (prev != null && prev != next) {
                if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
                        && next != null && !next.nowVisible) {
                    mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(prev);
                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                            "Resuming top, waiting visible to hide: " + prev);
                } else {
                    // The next activity is already visible, so hide the previous
                    // activity's windows right now so we can show the new one ASAP.
                    // We only do this if the previous is finishing, which should mean
                    // it is on top of the one being resumed so hiding it quickly
                    // is good.  Otherwise, we want to do the normal route of allowing
                    // the resumed activity to be shown so we can decide if the
                    // previous should actually be hidden depending on whether the
                    // new one is found to be full-screen or not.
                    if (prev.finishing) {
                        prev.setVisibility(false);
                        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                                "Not waiting for visible to hide: " + prev + ", waitingVisible="
                                + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
                                + ", nowVisible=" + next.nowVisible);
                    } else {
                        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                                "Previous already visible but still waiting to hide: " + prev
                                + ", waitingVisible="
                                + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
                                + ", nowVisible=" + next.nowVisible);
                    }
                }
            }
    
            // Launching this app's activity, make sure the app is no longer
            // considered stopped.
            try {
                AppGlobals.getPackageManager().setPackageStoppedState(
                        next.packageName, false, next.userId); /* TODO: Verify if correct userid */
            } catch (RemoteException e1) {
            } catch (IllegalArgumentException e) {
                Slog.w(TAG, "Failed trying to unstop package "
                        + next.packageName + ": " + e);
            }
    
            // We are starting up the next activity, so tell the window manager
            // that the previous one will be hidden soon.  This way it can know
            // to ignore it when computing the desired screen orientation.
            //这里准备开启页面
            boolean anim = true;
            if (prev != null) {
                if (prev.finishing) {
                    if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                            "Prepare close transition: prev=" + prev);
                    if (mNoAnimActivities.contains(prev)) {
                        anim = false;
                        mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
                    } else {
                        mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
                                ? TRANSIT_ACTIVITY_CLOSE
                                : TRANSIT_TASK_CLOSE, false);
                    }
                    prev.setVisibility(false);
                } else {
                    if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                            "Prepare open transition: prev=" + prev);
                    if (mNoAnimActivities.contains(next)) {
                        anim = false;
                        mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
                    } else {
                        //准备启动
                        mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
                                ? TRANSIT_ACTIVITY_OPEN
                                : next.mLaunchTaskBehind
                                        ? TRANSIT_TASK_OPEN_BEHIND
                                        : TRANSIT_TASK_OPEN, false);
                    }
                }
            } else {
                if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
                if (mNoAnimActivities.contains(next)) {
                    anim = false;
                    mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
                } else {
                    mWindowManager.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false);
                }
            }
    
            Bundle resumeAnimOptions = null;
            if (anim) {
                ActivityOptions opts = next.getOptionsForTargetActivityLocked();
                if (opts != null) {
                    resumeAnimOptions = opts.toBundle();
                }
                next.applyOptionsLocked();
            } else {
                next.clearOptionsLocked();
            }
    
            ActivityStack lastStack = mStackSupervisor.getLastStack();
            if (next.app != null && next.app.thread != null) {
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
                        + " stopped=" + next.stopped + " visible=" + next.visible);
    
                // If the previous activity is translucent, force a visibility update of
                // the next activity, so that it's added to WM's opening app list, and
                // transition animation can be set up properly.
                // For example, pressing Home button with a translucent activity in focus.
                // Launcher is already visible in this case. If we don't add it to opening
                // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a
                // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.
                final boolean lastActivityTranslucent = lastStack != null
                        && (!lastStack.mFullscreen
                        || (lastStack.mLastPausedActivity != null
                        && !lastStack.mLastPausedActivity.fullscreen));
                // The contained logic must be synchronized, since we are both changing the visibility
                // and updating the {@link Configuration}. {@link ActivityRecord#setVisibility} will
                // ultimately cause the client code to schedule a layout. Since layouts retrieve the
                // current {@link Configuration}, we must ensure that the below code updates it before
                // the layout can occur.
                synchronized(mWindowManager.getWindowManagerLock()) {
                    // This activity is now becoming visible.
                    if (!next.visible || next.stopped || lastActivityTranslucent) {
                        next.setVisibility(true);
                    }
    
                    // schedule launch ticks to collect information about slow apps.
                    next.startLaunchTickingLocked();
    
                    ActivityRecord lastResumedActivity =
                            lastStack == null ? null :lastStack.mResumedActivity;
                    ActivityState lastState = next.state;
    
                    mService.updateCpuStats();
    
                    if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next
                            + " (in existing)");
    
                    setResumedActivityLocked(next, "resumeTopActivityInnerLocked");
                    //更新进程信息
                    mService.updateLruProcessLocked(next.app, true, null);
                    updateLRUListLocked(next);
                    mService.updateOomAdjLocked();
    
                    // Have the window manager re-evaluate the orientation of
                    // the screen based on the new activity order.
                    boolean notUpdated = true;
    
                    if (mStackSupervisor.isFocusedStack(this)) {
    
                        // We have special rotation behavior when Keyguard is locked. Make sure all
                        // activity visibilities are set correctly as well as the transition is updated
                        // if needed to get the correct rotation behavior.
                        // TODO: Remove this once visibilities are set correctly immediately when
                        // starting an activity.
                        if (mStackSupervisor.mKeyguardController.isKeyguardLocked()) {
                            mStackSupervisor.ensureActivitiesVisibleLocked(null /* starting */,
                                    0 /* configChanges */, false /* preserveWindows */);
                        }
                        final Configuration config = mWindowManager.updateOrientationFromAppTokens(
                                mStackSupervisor.getDisplayOverrideConfiguration(mDisplayId),
                                next.mayFreezeScreenLocked(next.app) ? next.appToken : null,
                                        mDisplayId);
                        if (config != null) {
                            next.frozenBeforeDestroy = true;
                        }
                        notUpdated = !mService.updateDisplayOverrideConfigurationLocked(config, next,
                                false /* deferResume */, mDisplayId);
                    }
    
                    if (notUpdated) {
                        // The configuration update wasn't able to keep the existing
                        // instance of the activity, and instead started a new one.
                        // We should be all done, but let's just make sure our activity
                        // is still at the top and schedule another run if something
                        // weird happened.
                        ActivityRecord nextNext = topRunningActivityLocked();
                        if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES,
                                "Activity config changed during resume: " + next
                                        + ", new next: " + nextNext);
                        if (nextNext != next) {
                            // Do over!
                            mStackSupervisor.scheduleResumeTopActivities();
                        }
                        if (!next.visible || next.stopped) {
                            next.setVisibility(true);
                        }
                        next.completeResumeLocked();
                        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                        return true;
                    }
    
                    try {
                        // 判断是否需要触发onActivityResult函数
                        ArrayList<ResultInfo> a = next.results;
                        if (a != null) {
                            final int N = a.size();
                            if (!next.finishing && N > 0) {
                                if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                                        "Delivering results to " + next + ": " + a);
                                next.app.thread.scheduleSendResult(next.appToken, a);
                            }
                        }
    
                        //是否需要触发onNewIntent函数
                        if (next.newIntents != null) {
                            next.app.thread.scheduleNewIntent(
                                    next.newIntents, next.appToken, false /* andPause */);
                        }
    
                        // Well the app will no longer be stopped.
                        // Clear app token stopped state in window manager if needed.
                        next.notifyAppResumed(next.stopped);
    
                        EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
                                System.identityHashCode(next), next.getTask().taskId,
                                next.shortComponentName);
    
                        next.sleeping = false;
                        mService.showUnsupportedZoomDialogIfNeededLocked(next);
                        mService.showAskCompatModeDialogLocked(next);
                        next.app.pendingUiClean = true;
                        next.app.forceProcessStateUpTo(mService.mTopProcessState);
                        next.clearOptionsLocked();
                        //最后通过ActivityThread的scheduleResumeActivity函数进行启动
                        next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                                mService.isNextTransitionForward(), resumeAnimOptions);
    
                        if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
                                + next);
                    } catch (Exception e) {
                        // Whoops, need to restart this activity!
                        if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to "
                                + lastState + ": " + next);
                        next.state = lastState;
                        if (lastStack != null) {
                            lastStack.mResumedActivity = lastResumedActivity;
                        }
                        Slog.i(TAG, "Restarting because process died: " + next);
                        if (!next.hasBeenLaunched) {
                            next.hasBeenLaunched = true;
                        } else  if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
                                mStackSupervisor.isFrontStackOnDisplay(lastStack)) {
                            next.showStartingWindow(null /* prev */, false /* newTask */,
                                    false /* taskSwitch */);
                        }
                        mStackSupervisor.startSpecificActivityLocked(next, true, false);
                        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                        return true;
                    }
                }
    
                // From this point on, if something goes wrong there is no way
                // to recover the activity.
                try {
                    next.completeResumeLocked();
                } catch (Exception e) {
                    // If any exception gets thrown, toss away this
                    // activity and try the next one.
                    Slog.w(TAG, "Exception thrown during resume of " + next, e);
                    requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
                            "resume-exception", true);
                    if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                    return true;
                }
            } else {
                // Whoops, need to restart this activity!
                if (!next.hasBeenLaunched) {
                    next.hasBeenLaunched = true;
                } else {
                    if (SHOW_APP_STARTING_PREVIEW) {
                        next.showStartingWindow(null /* prev */, false /* newTask */,
                                false /* taskSwich */);
                    }
                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
                }
                if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
                mStackSupervisor.startSpecificActivityLocked(next, true, true);
            }
    
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return true;
        }
    

    这个函数就是对目标页的很多状态判断,还有pause我们的启动者,然后通知AT(ActivityThread)准备启动,我们继续查看AT内的启动逻辑

    @Override
            public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                    ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                    CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                    int procState, Bundle state, PersistableBundle persistentState,
                    List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                    boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
    
                updateProcessState(procState, false);
    
                ActivityClientRecord r = new ActivityClientRecord();
    
                r.token = token;
                r.ident = ident;
                r.intent = intent;
                r.referrer = referrer;
                r.voiceInteractor = voiceInteractor;
                r.activityInfo = info;
                r.compatInfo = compatInfo;
                r.state = state;
                r.persistentState = persistentState;
    
                r.pendingResults = pendingResults;
                r.pendingIntents = pendingNewIntents;
    
                r.startsNotResumed = notResumed;
                r.isForward = isForward;
    
                r.profilerInfo = profilerInfo;
    
                r.overrideConfig = overrideConfig;
                updatePendingConfiguration(curConfig);
    
                sendMessage(H.LAUNCH_ACTIVITY, r);
            }
    

    这个函数内创建了一个ActivityClientRecord对象,然后通过handler发送命令LAUNCH_ACTIVITY,我们看一下命令所对应的函数是什么吧

    case LAUNCH_ACTIVITY: {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
    
        r.packageInfo = getPackageInfoNoCheck(
                r.activityInfo.applicationInfo, r.compatInfo);
        handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }
    

    这个case下调用了handleLaunchActivity函数,我们继续跟进分析

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
            // If we are getting ready to gc after going to the background, well
            // we are back active so skip it.
            unscheduleGcIdler();
            mSomeActivitiesChanged = true;
    
            if (r.profilerInfo != null) {
                mProfiler.setProfiler(r.profilerInfo);
                mProfiler.startProfiling();
            }
    
            // Make sure we are running with the most recent config.
            handleConfigurationChanged(null, null);
    
            if (localLOGV) Slog.v(
                TAG, "Handling launch of " + r);
    
            // Initialize before creating the activity
            if (!ThreadedRenderer.sRendererDisabled) {
                GraphicsEnvironment.earlyInitEGL();
            }
            WindowManagerGlobal.initialize();
    
            //通过反射创建Activity的对象
            //并且触发attach、onCreate、onStart生命周期方法
            //此时我们也会自己掉用setContentView来组装DecorView
            Activity a = performLaunchActivity(r, customIntent);
    
            if (a != null) {
                r.createdConfig = new Configuration(mConfiguration);
                reportSizeConfigurations(r);
                Bundle oldState = r.state;
                //执行onResume生命周期方法,还会通知ViewRootImpl绘制页面
                handleResumeActivity(r.token, false, r.isForward,
                        !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
    
                if (!r.activity.mFinished && r.startsNotResumed) {
                    // The activity manager actually wants this one to start out paused, because it
                    // needs to be visible but isn't in the foreground. We accomplish this by going
                    // through the normal startup (because activities expect to go through onResume()
                    // the first time they run, before their window is displayed), and then pausing it.
                    // However, in this case we do -not- need to do the full pause cycle (of freezing
                    // and such) because the activity manager assumes it can just retain the current
                    // state it has.
                    performPauseActivityIfNeeded(r, reason);
    
                    // We need to keep around the original state, in case we need to be created again.
                    // But we only do this for pre-Honeycomb apps, which always save their state when
                    // pausing, so we can not have them save their state when restarting from a paused
                    // state. For HC and later, we want to (and can) let the state be saved as the
                    // normal part of stopping the activity.
                    if (r.isPreHoneycomb()) {
                        r.state = oldState;
                    }
                }
            } else {
                // If there was an error, for any reason, tell the activity manager to stop us.
                try {
                    ActivityManager.getService()
                        .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                                Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
        }
    

    到此startActivity的完整流程都全部呈现给大家了,里边的校验是真的多。涉及到的技术面也很广,偶尔读读源码还是可以收获很多的,上面的每一个判断,都是一个知识点,有些在开发中可以用到,有些判断是给系统app留的。

    了解更多Android知识,或者获取相关资料请加入Android技术开发交流2群:935654177。本群可免费获取Gradle,RxJava,小程序,Hybrid,移动架构,NDK,React Native,性能优化等技术教程!

    相关文章

      网友评论

        本文标题:终结篇:Android startActivity原理分析(基于

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