Android源碼分析之Activity的啟動(dòng)流程


說明:本文是基于Android6.0源碼來分析的


??本文只是從源碼的角度分析Activity的啟動(dòng)流程,并不會(huì)介紹Activity本身的一些特點(diǎn)涯塔,比如如何創(chuàng)建Activity鹤啡,如何開啟一個(gè)新的Activity惯驼,Activty的生命周期,啟動(dòng)模式等;如果你是一個(gè)剛?cè)腴T的Android開發(fā)祟牲,這篇文章可能對(duì)你來說有些晦澀難懂隙畜,如果你是一個(gè)老猿并且想對(duì)Activity的啟動(dòng)流程又一個(gè)比較直觀的了解,這片文章或許能夠幫助你说贝。

??由于Activity的啟動(dòng)會(huì)根據(jù)不同的狀態(tài)议惰,不同的啟動(dòng)模式,是否在一個(gè)應(yīng)用內(nèi)部啟動(dòng)一個(gè)Activity等不同情況而不同乡恕,如果都考慮進(jìn)來可能會(huì)比較繁瑣言询,不利于掌握和分析,所以我們就以一個(gè)Activty的啟動(dòng)模式是standard的標(biāo)準(zhǔn)模式并且是在同一個(gè)應(yīng)用里面且不帶Bundle參數(shù)的情況下來分析傲宜,下面我們就正式進(jìn)入分析的流程运杭。

??一般我們開啟一個(gè)Activity都是從startActivity方法開始的

 public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

接著接著調(diào)用Activity中的帶兩個(gè)參數(shù)的startActivity方法

@Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

option是null,所有會(huì)走else里的邏輯

 public void startActivityForResult(Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
    }

首次開啟mParent == null函卒,所以走if里面的邏輯辆憔,由于startActivityForResult的代碼有點(diǎn)多,所以我只貼我們關(guān)注的部分代碼

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            ...
        }
    }

如果想了解Instrumentation這個(gè)類报嵌,可以看一下這片文章Instrumentation的介紹虱咧;Now接著我們的Activity的啟動(dòng)流程繼續(xù)分析,調(diào)用Instrumentation#execStartActivity

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
                ...
                try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
                ...
            }

我們看到是通過 ActivityManagerNative.getDefault()來啟動(dòng)的锚国,那么getDefault()是什么呢腕巡?

 static public IActivityManager getDefault() {
        return gDefault.get();
    }
    
    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

其實(shí)就是在獲取ActivityManagerServer。
IActivityManager是個(gè)接口血筑,ActivityManagerNative是一個(gè)IActivityManager是接口的一個(gè)抽象實(shí)現(xiàn)類绘沉,ActivityManagerService又是ActivityManagerNative的一個(gè)具體的實(shí)現(xiàn)類。所以最終調(diào)用的是云挟,ActivityManagerService#startActivity()方法梆砸。

 @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, options,
            UserHandle.getCallingUserId());
    }

    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, false, userId, null, null);
    }

就是不斷的調(diào)用ActivityManagerService的重載方法,然后再調(diào)用ActivityStackSupervisor#startActivityMayWait方法园欣。

 final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
            Bundle options, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {
                ...
                
            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage,
                    realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                    componentSpecified, null, container, inTask);
                ...
                
            }

然后又調(diào)用了重載的startActivityLocked()帖世,這個(gè)方法真的是和老太太的腳一樣,又臭又長(zhǎng)啊沸枯,但是重點(diǎn)就在這個(gè)方法最后面

final int startActivityLocked(IApplicationThread caller,
            Intent intent, String resolvedType, ActivityInfo aInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode,
            int callingPid, int callingUid, String callingPackage,
            int realCallingPid, int realCallingUid, int startFlags, Bundle options,
            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
            ActivityContainer container, TaskRecord inTask) {
                ...
                 err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);
                ...
            }

結(jié)合調(diào)用了startActivityUncheckedLocked()日矫,這個(gè)方法其實(shí)也不簡(jiǎn)單,也是很長(zhǎng)绑榴,邏輯很多,但是重要的方法也是在最后幾行調(diào)用的哪轿。

final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
            boolean doResume, Bundle options, TaskRecord inTask) {
                ...
                targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
                ...
            }

接著調(diào)用了ActivityStack#startActivityLocked方法,怎么說呢,這個(gè)方法也會(huì)比較長(zhǎng)的翔怎,但是相較于前面的兩個(gè)方法窃诉,這個(gè)方法還是比較端的杨耙,我們只貼關(guān)鍵代碼

final void startActivityLocked(ActivityRecord r, boolean newTask,
            boolean doResume, boolean keepCurTransition, Bundle options) {
                ...
                 if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }
                ...
            }

接著調(diào)用了ActivityStack#resumeTopActivitiesLocked方法

 boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
            Bundle targetOptions) {
                ...
                   if (!addingToTask && reuseTask == null) {
                        // We didn't do anything...  but it was needed (a.k.a., client
                        // don't use that intent!)  And for paranoia, make
                        // sure we have correctly resumed the top activity.
                          //重點(diǎn)方法 
                        if (doResume) {
                          targetStack.resumeTopActivityLocked(null, options);
                            if (!movedToFront) {
                                // Make sure to notify Keyguard as well if we are not running an app
                                // transition later.
                                notifyActivityDrawnForKeyguard();
                            }
                        } else {
                            ActivityOptions.abort(options);
                        }
                        return ActivityManager.START_TASK_TO_FRONT;
                    }
                ...
            }

接著調(diào)用了ActivityStack#resumeTopActivityLocked方法


    final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
        if (mStackSupervisor.inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
                mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
                mService.updateSleepIfNeededLocked();
            }
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        return result;
    }

接著調(diào)用resumeTopActivityInnerLocked方法,這個(gè)方法也很長(zhǎng)飘痛。

 private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
     ...
      mStackSupervisor.startSpecificActivityLocked(next, true, true);
     ...
 }

接著調(diào)用ActivityStackSupervisor#startSpecificActivityLocked方法,這個(gè)方法還是比較重要的珊膜,里面有行代碼還是很重要的,那就是 mService.startProcessLocked方法宣脉,這個(gè)方法就是開啟一個(gè)新app的時(shí)候創(chuàng)建新進(jìn)程的方法车柠,這個(gè)不展開了,后面會(huì)寫一片Android應(yīng)用的啟動(dòng)流程塑猖,就會(huì)設(shè)計(jì)到這里了竹祷。

void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
                ...
          
        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    // Don't add this if it is a platform component that is marked
                    // to run in multiple processes, because this is actually
                    // part of the framework so doesn't make sense to track as a
                    // separate apk in the process.
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }

            // If a dead object exception was thrown -- fall through to
            // restart the application.
        }

        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
                ...
    }

這里調(diào)用的就是ActivityStackSupervisor#realStartActivityLocked方法,這個(gè)方法也很長(zhǎng)羊苟,我們只關(guān)注重點(diǎn)的方法塑陵,不然就會(huì)陷入只見樹木,不見森林的尷尬境地蜡励。

  final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {
            ...
              // switch back to it faster and look better.
        if (isFrontStack(stack)) {
            mService.startSetupActivityLocked();
        }
            ...
            }

接著掉了ActivityManagerService#startSetupActivityLocked

 void startSetupActivityLocked() {
     ...
      mStackSupervisor.startActivityLocked(null, intent, null, ri.activityInfo,
                            null, null, null, null, 0, 0, 0, null, 0, 0, 0, null, false, false,
                            null, null, null);
     ...
 }

接著又回調(diào)到了ActivityStackSupervisor#startActivityLocked方法,haha這個(gè)方法也很長(zhǎng)猿妈,不過別慌,我們還是老規(guī)矩巍虫,只貼重點(diǎn)方法

 final int startActivityLocked(IApplicationThread caller,
            Intent intent, String resolvedType, ActivityInfo aInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode,
            int callingPid, int callingUid, String callingPackage,
            int realCallingPid, int realCallingUid, int startFlags, Bundle options,
            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
            ActivityContainer container, TaskRecord inTask) {
                ...
                 err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);
                ...
            }

然后是掉了ActivityStackSupervisor#startActivityUncheckedLocked,方法很長(zhǎng)鳍刷,我們也只看重點(diǎn)

 final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
            boolean doResume, Bundle options, TaskRecord inTask) {
                ...
                   targetStack.startActivityLocked(r, newTask, doResume, keepCurTranstion, options);
                ...
            }

然后掉了ActivityStack#startActivityLocked方法

 final void startActivityLocked(ActivityRecord r, boolean newTask,
            boolean doResume, boolean keepCurTransition, Bundle options) {
                ...
                
        if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }
                ...
            }

然后ActivityStackSupervisor#resumeTopActivitiesLocked方法

 boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
            Bundle targetOptions) {
            //這個(gè)地方要注意占遥,調(diào)用的不是循環(huán)里面的resumeTopActivityLocked方法。
                ...
                   if (isFrontStack(targetStack)) {
            result = targetStack.resumeTopActivityLocked(target, targetOptions);
        }
                ...
            }

然后就是ActivityStack#resumeTopActivityLocked方法

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
        if (mStackSupervisor.inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
                mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
                mService.updateSleepIfNeededLocked();
            }
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        return result;
    }
    
 final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
       ...
        result = resumeTopActivityInnerLocked(prev, options);
       ...
    }
//這個(gè)方法也很長(zhǎng)输瓜,只貼重點(diǎn)方法
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
    ...
     mStackSupervisor.startSpecificActivityLocked(next, true, true);
    ...
}

接著回到ActivityStackSupervisor#startSpecificActivityLocked

void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
                ...
                 realStartActivityLocked(r, app, andResume, checkConfig);
                ...
            }

走了這么多不瓦胎,而realStartActivityLocked方法就是真正的去開啟一個(gè)Activity的方法。

   final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {
                ...
                 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
                    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
                ...
            }

app.thread其實(shí)就是ApplicationThread尤揣,所以最后調(diào)用的其實(shí)就是ApplicationThread#scheduleLaunchActivity

  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) {
                    ...
                     sendMessage(H.LAUNCH_ACTIVITY, r);
                    ...
                }

最終發(fā)送handler消息給H

 public void handleMessage(Message msg) {
     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);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
       } 
       break;
 }
 
  private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { 
      ...
      Activity a = performLaunchActivity(r, customIntent);
      
        handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);
      ...
  }
  //順便再提一嘴搔啊,activity的布局繪制其實(shí)就在handleResumeActivity方法倆面的這一行代碼開始的
   wm.addView(decor, l);

接著看handleLaunchActivity方法

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
     ...
     Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            //這里就是創(chuàng)建activity的實(shí)例,可以看出是通過反射創(chuàng)建的
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

        try {
        //這部分是創(chuàng)建應(yīng)用的application的地方北戏,
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
            if (localLOGV) Slog.v(
                    TAG, r + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + r.packageInfo.getPackageName()
                    + ", comp=" + r.intent.getComponent().toShortString()
                    + ", dir=" + r.packageInfo.getAppDir());

            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                   //這里就是通過Instrumentation去調(diào)用activity的onCreate方法的地方负芋, mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {
                    if (r.isPersistable()) {
                        if (r.state != null || r.persistentState != null) {
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                    r.persistentState);
                        }
                    } else if (r.state != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
                if (!r.activity.mFinished) {
                    activity.mCalled = false;
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    }
                    if (!activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPostCreate()");
                    }
                }
            }
            r.paused = true;

            mActivities.put(r.token, r);

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to start activity " + component
                    + ": " + e.toString(), e);
            }
        }

        return activity;
     ...
 }
 
  public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
            //如果application存在直接返回,這里可以確定一個(gè)app只有一個(gè)application了
        if (mApplication != null) {
            return mApplication;
        }
        ...
        }
        
  public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        //Here we go,真正的去執(zhí)行activity的onCreate的地方
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }
    
    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        restoreHasCurrentPermissionRequest(icicle);
        /真正的onCreate的方法執(zhí)行的地方嗜愈。
        onCreate(icicle, persistentState);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }

上面這部分的代碼估計(jì)能解決你對(duì)activity的大部分疑問旧蛾,
里買呢又創(chuàng)建activity的過程,onCreate方法的調(diào)用等蠕嫁,具體邏輯在上面的代碼中已經(jīng)寫處理啊了锨天。


到這里Acvitiy的啟動(dòng)流程我們就介紹完了,下面我會(huì)把Activity的啟動(dòng)流程圖貼出來剃毒,相對(duì)干巴巴的代碼病袄,我們可能會(huì)覺得流程圖更清晰一些搂赋,就像會(huì)說話的人,眼睛看到那里他好像就能告訴我們?cè)诹鞒痰氖裁吹胤搅艘娌蝗绻覀冊(cè)诳创a邏輯的時(shí)候覺得思緒很亂脑奠,往往流程圖能更清晰的從全局去理解和掌握代碼的執(zhí)行流程,如果分析的那些地方有錯(cuò)誤不正確還請(qǐng)指出左刽,謝謝捺信。

  • 流程圖

    • 流程圖地址,流程圖是用在線的ProcessOn軟件做的欠痴。
      Activity啟動(dòng)流程.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末迄靠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子喇辽,更是在濱河造成了極大的恐慌掌挚,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件菩咨,死亡現(xiàn)場(chǎng)離奇詭異吠式,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)抽米,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門特占,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人云茸,你說我怎么就攤上這事是目。” “怎么了标捺?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵懊纳,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我亡容,道長(zhǎng)嗤疯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任闺兢,我火速辦了婚禮茂缚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘列敲。我一直安慰自己阱佛,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布戴而。 她就那樣靜靜地躺著凑术,像睡著了一般。 火紅的嫁衣襯著肌膚如雪所意。 梳的紋絲不亂的頭發(fā)上淮逊,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天催首,我揣著相機(jī)與錄音,去河邊找鬼泄鹏。 笑死郎任,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的备籽。 我是一名探鬼主播舶治,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼车猬!你這毒婦竟也來了霉猛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤珠闰,失蹤者是張志新(化名)和其女友劉穎惜浅,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體伏嗜,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡坛悉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了承绸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片裸影。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖军熏,靈堂內(nèi)的尸體忽然破棺而出空民,到底是詐尸還是另有隱情,我是刑警寧澤羞迷,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站画饥,受9級(jí)特大地震影響衔瓮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜抖甘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一热鞍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧衔彻,春花似錦薇宠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至柄沮,卻和暖如春回梧,著一層夾襖步出監(jiān)牢的瞬間废岂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工狱意, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留湖苞,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓详囤,卻偏偏與公主長(zhǎng)得像财骨,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子藏姐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容