源碼探索系列3---四大金剛之Activity的啟動過程完全解析

在不同版本API啸臀,底層實現(xiàn)有些不一樣烹俗,所以這里貼出現(xiàn)在在看的API版本號
API: 23


關(guān)于Activity的四個啟動flag窘奏,這里下次再說。
先說下我們熟悉的一句吧

startActivity(new Intent(this,Test2Activity.class));

相信我們對這句太熟悉不過了右蒲,不過說到這里阀湿,我想說下關(guān)于寫Intent的一個感覺好的實踐
相信你已寫膩了一堆這樣的intent,用起來確實很不好的瑰妄,就像下面這樣

Intent newIntent= new Intent(this,Test2Activity.class);
        newIntent.putExtra("data1", "trialData1");
        Bundle bundle=new Bundle();
        bundle.putSerializable("key","trialData"); 
        startActivity(newIntent);

像這種方式我在很多開源項目看到了很多這樣的寫法陷嘴,這種不好的方式在于,很多我們要跳到同一個Activity里面去時候翰撑,重復(fù)寫了罩旋,這很顯然不適合DRY原則,而且我們在另外一個Activity獲取數(shù)據(jù)時候眶诈,也需要記住這些Key涨醋,這不太好!看到的另外一種方式就是直接寫一個IntentUtil類逝撬,里面寫滿各種Intent浴骂,感覺這種也不是很好!雖然沒重復(fù)了宪潮,不過在獲取數(shù)據(jù)方面還不是很好溯警,還需要定義一些Constant數(shù)據(jù),這里提供我個人覺得好的方式狡相,在我們的Activity里面寫一個靜態(tài)的makeIntent()函數(shù)梯轻。
如下:

public class Test2Activity extends AppCompatActivity {


    public static final String EXTRA_DATA = "extra_data";

    public static Intent makeIntent(Context mContext, String data) {
        return new Intent(mContext, Test2Activity.class).putExtra(EXTRA_DATA, data);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test2);
         //獲取傳過來的數(shù)據(jù)
        String result = getIntent().getStringExtra(EXTRA_DATA);
    }
}

之后我們需要調(diào)整到這個界面,只需要這么寫

startActivity(Test2Activity.makeIntent(this,"data"));

通過這個靜態(tài)方法尽棕,我們在數(shù)據(jù)里面讀取方面都很簡單喳挑,而且啟動的時候也知道是要跳到那個界面去,重要是看起來很簡單!而且不需要去定義一個常量類來記錄這些數(shù)據(jù)的Key

最后的一個大殺器就是直接寫成模板滔悉。哈哈伊诵,之后就可以快捷的自己生成了!回官!


這里寫圖片描述
這里寫圖片描述

以后我們就這樣曹宴,就生成了,不再需要重復(fù)寫了歉提!

這里寫圖片描述
這里寫圖片描述

是不是很好5烟埂!唯袄!



StartActivity

上面分享個人覺得好的最佳實戰(zhàn)弯屈,下面就從這個開始剖析底層是如何啟動這個Activity的。

@Override
public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}
 
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
   if (options != null) {
       startActivityForResult(intent, -1, options);
   } else {
        startActivityForResult(intent, -1);
    }
}

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

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());
        }
        if (requestCode >= 0) {
            // If this start is requesting a result, we can avoid making
            // the activity visible until the result is received.  Setting
            // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
            // activity hidden during this time, to avoid flickering.
            // This can only be done when a result is requested because
            // that guarantees we will get information back when the
            // activity is finished, no matter what happens to it.
            mStartedActivity = true;
        }

        cancelInputsAndStartExitTransition(options);
        // TODO Consider clearing/flushing other event sources and events for child windows.
    } else {
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            // Note we want to go through this method for compatibility with
            // existing applications that may have overridden it.
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}

從上面代碼恋拷,我們發(fā)現(xiàn)一個很有趣的事實资厉,就是他底層居然調(diào)用的是startActivityForResult()函數(shù),而且RequestCode是-1。

if (requestCode >= 0) {
    mStartedActivity = true;
}

結(jié)合上面這個判斷條件蔬顾,這樣我們就理解宴偿,為何在startActivity的RequestCode 有這么句解釋

requestCode - If >= 0, this code will be returned in
onActivityResult() when the activity exits.

我們需要注意到這么一句,這句實際的執(zhí)行了intent程序

 Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);

不知道對MainThread這個單詞還記得嘛诀豁,在前篇文章說Looper的時候里面有介紹到這個單詞窄刘,創(chuàng)說中的主線程,他get回ApplicationThread舷胜,我們的app線程娩践。另外這個Instrumentation居然出現(xiàn)在這里,我們在介紹測試教程的時候,很多類都是基礎(chǔ)于它的翻伺,就讓我們繼續(xù)看這個execStartActivity到底做了什么

 public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        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);
        }
        return null;
    }

(題外話:當(dāng)年看《Android系統(tǒng)源代碼情景分析》的時候吐槽里面都是貼代碼的材泄,現(xiàn)在自己分析時候也貼了好多,哈哈)
我們看到里面結(jié)尾處的最重要的一句吨岭,好長的一句ActivityManagerNative實際執(zhí)行了這個startActivity的工作拉宗。

int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);

再近一步的看,我們看到這個ActivityManagerNative 居然是個抽象類辣辫,而且基礎(chǔ)于Binder旦事,實現(xiàn)了IActivityManager這個接口。另外要提一點就是這個@hide急灭,他的作用很神奇的姐浮,可以使類在編譯時不對外開放,但是運行的時候這些類和API都是可以訪問的葬馋。所以要直接使用是會報錯的单料,需要修改下設(shè)置的,具體有興趣的点楼,關(guān)于他的經(jīng)一步內(nèi)容扫尖,找下資料吧

/** {@hide} */
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
    
    /**
     * Retrieve the system's default/global activity manager.
     */
    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;
            }
        };
}

好吧,一個神奇的Binder掠廓,讓我們繼續(xù)看下去
很遺憾的是换怖,現(xiàn)在都凌晨一點多了,我居然還沒找到傳說中的ActivityManagerService這個類在哪里s扒啤沉颂!
好消息是,這玩意經(jīng)過一番折騰悦污,終于發(fā)現(xiàn)一個事實铸屉,這各類在Android.jar里面沒有,得去源碼里面找切端。呵呵彻坛。初學(xué),這類坑難免踏枣。
位置是你的SDK位置\sources\android-23\com\android\server\am
打開一看昌屉,簡直瘋了,這個類居然

20640
20640
20640
20640

簡直不敢相信茵瀑,怪不得一個文件有871KB大小间驮,服了,這代碼量马昨,簡直夠一個簡單的app的整個代碼量了竞帽!
先上一張偷來的大圖扛施,整個啟動的流程。

這里寫圖片描述
這里寫圖片描述

還沒看完一半的代碼屹篓。呵呵
一折騰都一點半了煮嫌,明天繼續(xù)寫吧。抱虐。。


讓我們繼續(xù)看下了這神奇的ActivityManagerService

@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);
}

這些參數(shù)也太多了把饥脑,系統(tǒng)的源碼這樣如此的復(fù)雜恳邀。

  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);

      ...
}

這個方法也好長,這里貼下最重要的一句startActivityLocked()

 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) {
    int err = ActivityManager.START_SUCCESS;

    ...
    
    err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
            startFlags, true, options, inTask);

    if (err < 0) {
        // If someone asked to have the keyguard dismissed on the next
        // activity start, but we are not actually doing an activity
        // switch...  just dismiss the keyguard now, because we
        // probably want to see whatever is behind it.
        notifyActivityDrawnForKeyguard();
    }
    return err;
}

越到后面的類都好變態(tài)灶轰,參數(shù)看起來可怕谣沸,整個類的行數(shù)都用千來做單位,看起來真的好辛苦笋颤,那些設(shè)計這個系統(tǒng)的一開始得花了多少功夫叭楦健!根據(jù)查看伴澄,他底部是這個方法

    err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
            startFlags, true, options, inTask);

好想跳過赋除。。非凌。這個方法里面內(nèi)容也是超級龐大的举农。看到好難過敞嗡。颁糟。
里面調(diào)整到resumeTopActivitiesLocked()接著到了

 boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
        Bundle targetOptions) {
    if (targetStack == null) {
        targetStack = mFocusedStack;
    }
    // Do targetStack first.
    boolean result = false;
    if (isFrontStack(targetStack)) {
        result = targetStack.resumeTopActivityLocked(target, targetOptions);
    }

    ...
    return result;
}

下面這個是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;
}

繼續(xù)堅持看下去。喉悴。

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
    if (DEBUG_LOCKSCREEN) mService.logLockScreen("");

      ....
     
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
     ...

}

蒼天棱貌,終于這個方法短一點了,都敢直接貼上來了箕肃,前面都是幾百行的婚脱,而且重點是很多操作是沒深入看,都暈暈的I紫瘛起惕!

  void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.task.stack.setLaunchTime(r);

        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);
    }

好日子到頭了,又繼續(xù)看下吧

final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {

           ...
           
            app.forceProcessStateUpTo(mService.mTopProcessState);
            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);
        ...

        return true;
    }

看這些咏删,突然想說惹想,知道個整個流程真不容易,好復(fù)雜的流程督函,一開始搭架構(gòu)的人能力也太犀利了嘀粱!設(shè)計這么多激挪!
看到這里我們的線索中斷了下,因為app.thread的這個thread是一個接口锋叨,繼承IInterface垄分,成了個Binder,我們需要找到真正干活的人

public interface IApplicationThread extends IInterface { 

}

我們搜索了這個ProcessRecord類娃磺,發(fā)現(xiàn)在他的makeActivie里面對他進(jìn)行了賦值

 public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) {
  
     ....
     
    thread = _thread;
}

是時候了薄湿,使用傳說中的Alt+Ctrl+Shift+F7組合鍵,我們發(fā)現(xiàn)他的來源是在AMS里面偷卧,我的跪了,感覺新新苦苦回到革命前的感覺啊豺瘤。

這里寫圖片描述
這里寫圖片描述

接著我們繼續(xù)追尋,發(fā)現(xiàn)下面這個入口

@Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

既然是Override的方法听诸,我們回來看的聲明

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {

}

好吧坐求,一個熟悉的東西,我們在ActivityManagerNative發(fā)現(xiàn)了最重要的信息晌梨,居然跳回了這里桥嗤!

case ATTACH_APPLICATION_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IApplicationThread app = ApplicationThreadNative.asInterface(
                    data.readStrongBinder());
            if (app != null) {
                attachApplication(app);
            }
            reply.writeNoException();
            return true;
        }

嫌疑犯ApplicationThreadNative出現(xiàn)了,這名字感覺很有規(guī)律啊仔蝌,XXXNative和我們的ActivityManagerNative是類似的泛领,萬惡的Binder又出現(xiàn)了。他的具體實現(xiàn)是下面這個ApplicationThread敛惊,居然是ActivityThread 里面的內(nèi)部類师逸,不要問我怎么知道的

private class ApplicationThread extends ApplicationThreadNative


 ....
 
public abstract class ApplicationThreadNative extends Binder
    implements IApplicationThread {
    
}

既然回到了ApplicationThread,我們就繼續(xù)吧豆混,我快看膩了篓像,不知道看這個干什么。皿伺。
但最少我們找到了真正干活的人T北纭!鸵鸥!希望你看這么久奠滑,不會忘了我們是要找下面這句

 app.thread.scheduleLaunchActivity()

好了,我們繼續(xù)看他的具體內(nèi)容把

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
            Bundle state, List<ResultInfo> pendingResults,
            List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
            String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
        ActivityClientRecord r = new ActivityClientRecord();

        r.token = token;
        r.ident = ident;
        r.intent = intent;
        r.activityInfo = info;
        r.compatInfo = compatInfo;
        r.state = state;

        r.pendingResults = pendingResults;
        r.pendingIntents = pendingNewIntents;

        r.startsNotResumed = notResumed;
        r.isForward = isForward;

        r.profileFile = profileName;
        r.profileFd = profileFd;
        r.autoStopProfiler = autoStopProfiler;

        updatePendingConfiguration(curConfig);

        queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
    }

發(fā)送消息妒穴,又事坑

private void queueOrSendMessage(int what, Object obj) {
       queueOrSendMessage(what, obj, 0, 0);
}

private void queueOrSendMessage(int what, Object obj, int arg1) {
    queueOrSendMessage(what, obj, arg1, 0);
}

private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
    synchronized (this) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        mH.sendMessage(msg);
    } 
}

final H mH = new H();

我們看到宋税,他最后居然用一個Handler發(fā)送消息,呵呵讼油,而且這個handler居然那么簡單的名字

private class H extends Handler {

    public static final int LAUNCH_ACTIVITY         = 100;
    public static final int PAUSE_ACTIVITY          = 101; 

    ...
 
    public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + msg.what);
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                ActivityClientRecord r = (ActivityClientRecord)msg.obj;

                r.packageInfo = getPackageInfoNoCheck(
                        r.activityInfo.applicationInfo, r.compatInfo);
                handleLaunchActivity(r, null);
            } break;
            case RELAUNCH_ACTIVITY: {
                ActivityClientRecord r = (ActivityClientRecord)msg.obj;
                handleRelaunchActivity(r);
            } break;
            
            ...
        }
        if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what);
    }
}

繼續(xù)看下去吧杰赛,handleLaunchActivity(),寫到這里,很想說矮台,沒什么動力乏屯,估計沒什么人沒事會把整個系統(tǒng)的源碼看一遍根时。實在好累的感覺

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    

    if (r.profileFd != null) {
        mProfiler.setProfiler(r.profileFile, r.profileFd);
        mProfiler.startProfiling();
        mProfiler.autoStopProfiler = r.autoStopProfiler;
    }

    // Make sure we are running with the most recent config.
    handleConfigurationChanged(null, null);

    if (localLOGV) Slog.v(
        TAG, "Handling launch of " + r);
    Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        Bundle oldState = r.state;
        handleResumeActivity(r.token, false, r.isForward);

        
            r.paused = true;
        }
    }  
    
    ...
}

恭喜你,看到這里基本到尾聲了辰晕,我們的Activity被創(chuàng)建出來了蛤迎,這個函數(shù)一百多行,實在太長了含友,就不貼了
替裆,一個函數(shù)長度都夠我平時寫的一個類的長度了。
在performLaunchActivity()函數(shù)里面窘问,對我們的Activity粘貼到window辆童,設(shè)置主題,設(shè)置Context 南缓,調(diào)用OnCreate函數(shù)等等操作。

然后就是在handleResumeActivity里面荧呐,會調(diào)用我們最熟悉不過的onResume()函數(shù)汉形!
好了,到這里結(jié)束1恫8沤!7逄隆岔冀!

關(guān)于別的Activity的生命周期函數(shù)是怎么調(diào)用到的,下次有空再繼續(xù)寫概耻!
就這點內(nèi)容使套,看了我?guī)讉€小時,得洗澡先了>媳侦高!


后記

第一次自己看完這么長的一個流程,真的是不容易厌杜,寫這篇花了我兩個晚上
雖然覺得挺好奉呛,不過也不知道有什么意義呢,看完整個啟動的生命周期夯尽!
寫系統(tǒng)代碼的人也是牛逼瞧壮,繞來繞去的,這么長流程匙握,想做到?jīng)]bug的話真的不容易咆槽!
我看著就累了,特別是看到那個AMS里面居然兩萬多行HΨ摹B拊巍济欢!
這一個類小渊,真的完全都夠?qū)懸粋€中小型的項目的代碼量了
發(fā)現(xiàn)自己貼了好多代碼法褥,整篇文章都16,000多了酬屉,好長0氲取!
估計一般人都不會看呐萨,就當(dāng)記錄下整個流程杀饵,
下次遇到問題,方便自己查閱

-------------------再次更新--------------------

補充下一個笑話

深夜谬擦,交警查車切距,突然插到一部車的后尾箱放了幾百萬美元,在這樣一個夜黑風(fēng)高之晚惨远,顯然很有嫌疑谜悟,所以警察質(zhì)問司機:“為何這么晚還帶這么多錢跑?”北秽,實際雖然有點緊張葡幸,但就回答了句,“嗯贺氓,我能”蔚叨。
這個是以前在知乎看到的。具體大意入手辙培,最終想說的就是那么兩個字蔑水,因為我能。>.<


參考:
整個流程圖扬蕊,來自下面這篇文章
Activity啟動創(chuàng)建 (AcitivtyManageService,ActivityThread,Activity)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末肤粱,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子厨相,更是在濱河造成了極大的恐慌领曼,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛮穿,死亡現(xiàn)場離奇詭異庶骄,居然都是意外死亡,警方通過查閱死者的電腦和手機践磅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門单刁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事羔飞》握粒” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵逻淌,是天一觀的道長么伯。 經(jīng)常有香客問我,道長卡儒,這世上最難降的妖魔是什么田柔? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮骨望,結(jié)果婚禮上硬爆,老公的妹妹穿的比我還像新娘。我一直安慰自己擎鸠,他們只是感情好缀磕,可當(dāng)我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著劣光,像睡著了一般袜蚕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赎线,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天廷没,我揣著相機與錄音糊饱,去河邊找鬼垂寥。 笑死,一個胖子當(dāng)著我的面吹牛另锋,可吹牛的內(nèi)容都是我干的滞项。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼夭坪,長吁一口氣:“原來是場噩夢啊……” “哼文判!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起室梅,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤戏仓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后亡鼠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赏殃,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年间涵,在試婚紗的時候發(fā)現(xiàn)自己被綠了仁热。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡勾哩,死狀恐怖抗蠢,靈堂內(nèi)的尸體忽然破棺而出举哟,到底是詐尸還是另有隱情,我是刑警寧澤迅矛,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布妨猩,位于F島的核電站,受9級特大地震影響诬乞,放射性物質(zhì)發(fā)生泄漏册赛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一震嫉、第九天 我趴在偏房一處隱蔽的房頂上張望森瘪。 院中可真熱鬧,春花似錦票堵、人聲如沸扼睬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窗宇。三九已至,卻和暖如春特纤,著一層夾襖步出監(jiān)牢的瞬間军俊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工捧存, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留粪躬,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓昔穴,卻偏偏與公主長得像镰官,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子吗货,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,060評論 2 355

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