Activity的啟動流程
考察要點:
- 啟動Activity會經歷哪些生命週期回撥
- 冷啟動大致流程,涉及哪些元件,通訊過程是怎麼樣的?
- Activity啟動過程中,生命週期回撥的原理?
總的流程圖:
1. 程序A與AMS的互動過程
此處以跨程序啟動Activity分析一下原始碼流程:
-
A呼叫startActivity時,需要與AMS互動,此時需要需要獲取到AMS的代理物件Binder也就是上圖的AMP,通過ActivityManagerNative.getDefault()獲得,並呼叫AMP的startActivity方法,然後會通過mRemote.transact方法進行Binder通訊,在AMS的onTransact方法裡面會獲取到請求的Activity引數資訊:
mRemote.transact(START_ACTIVITY_TRANSACTION,data,reply,0); ... @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags){ switch(code){ case START_ACTIVITY_TRANSACTION:{ startActivity(app,callingPackage,intent,...) } } }
-
AMS裡面的startActivity方法最主要會去呼叫startSpecificActivityLocked函式,在此函式裡面會去判斷目標程序是否已經存在,並且目標向AMS註冊過它自己的ApplicationThread也就是上圖ATP代理物件,如果這兩個條件都滿足會去呼叫realStartActivityLocked方法,這個方法我們後面再看。如果上述條件不滿足時,會去呼叫mService.startProcessLocked(r.processName,...)方法啟動程序。
2. AMS啟動目標程序B
![](https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/2/7/1702043547d09967~tplv-t2oaga2asx-watermark.image)
-
startProcessLocked方法首先呼叫Process.start("android.app.ActivityThread",)方法會向Zygote傳送一個啟動程序的請求,並告知Zygote程序啟動之後,載入ActivityThread這個類的入口main函式,啟動完成後返回程序的pid,並向AMS的Handler傳送一個延遲訊息,為的是要求目標程序啟動後,10秒鐘內需要向AMS報告,不然的話AMS就會清除目標程序的相關資訊。
-
Process.start方法會去呼叫startViaZygote(processClass,)函式,這個函式主要做了兩件事,一件就是開啟通往Zygote的Socket,第二件事就是通過Socket傳送啟動程序引數。
-
Zygote端主要邏輯是在runOnce函式,函式內呼叫Zygote.forkAndSpecialize(...)建立子程序,建立完成之後就分別在父程序和子程序裡面做各自的事情
-
父程序通過hanleParentProc(pid)把子程序的pid通過Socket傳送給AMS
-
子程序呼叫handleChildProc函式,做一些通用的初始化,比如啟用Binder機制;執行應用程式的入口函式,也就是ActivityThread的Main函式
-
ActivityThread的main函式,裡面會建立一個ActivityThread物件,並呼叫thread.attach(false),為的是向AMS報到,上面第一條裡面有提到。
-
attach方法裡面,其實是一個跨程序的呼叫,首先通過
IActivityManager mgr = ActivityManagerNative.getDefault();
獲取到AMS的Binder代理物件,然後呼叫
mgr.attachApplication(mAppThread);
mAppThread是應用端的一個Binder物件ApplicationThread,也就是最上面一張圖的ATP,這樣AMS端就可以呼叫應用端了。
-
attachApplication方法裡面,最主要有兩個方法,一個是通過傳入的ApplicationThread物件,呼叫bindApplication初始化Application物件,另一個就是通過
mStactSupervisor.attachApplicationLoacked(app);
初始化掛起的Activity物件。
-
在attachApplicationLoacked函式裡,會呼叫
ActivityRecord hr = stack.topRunningActivityLocked(null);
其中要明白AMS裡面有兩個棧,一個是Launch桌面棧,一個就是非桌面棧mFocusedStack,此處的stack就是mFocusedStack,它會將棧頂的ActivityRecord返回出來,我們的目標Activity早就放置在了棧頂,只是一直沒有初始化。然後呼叫
realStartActivityLocked(hr,app,true,true);
方法,來啟動Activity,如果我們不是啟動另外一個程序,而是同一程序,那麼這第二大部分就不會存在了,而是直接呼叫realStartActivityLocked方法。
3. 應用端Activity啟動的幾個步驟
-
realStartActivityLocked函式會呼叫app.thread.scheduleLaunchActivity(new Intent(r.intent),...);也就是通過之前註冊的Binder物件ATP,呼叫scheduleLaunchActivity函式,在scheduleLaunchActivity函式裡面:
ActivityClientRecord r = new ActivityClientRecord(); ... sendMessage(H.LAUNCH_ACTIVITY,r);
封裝了一個ActivityClientRecord訊息,然後丟到主執行緒的Handler(mH)裡。
-
在主執行緒裡面
final ActivityClientRecord r = (ActivityClientRecord)msg.obj ; r.packageInfo = getPackageInfoNoCheck(...); handleLaunchActivity(r,null);
getPackageInfoNoCheck 函式主要是用來生成一個LoadedApk物件,它用來儲存我們的apk資訊,因為後面我們需要一個ClassLoader去載入Apk裡面的Activity類,所以這裡提前準備好。
-
handleLaunchActivity裡面分為兩個部分,一個是performLaunchActivity函式,一個是handleResumeActivity函式。
-
performLaunchActivity
Activity activity = mInstrumentation.newActivity(...); //返回之前建立好的 Application app = r.packageInfo.makeApplication(false,mInstrumentation); //生成ContextImpl Context appContext = createBaseContextForActivity(r,activity); //給activity繫結上下文和一些初始化的工作,如createPhoneWindow activity.attach(appContext,...); mInstrumentation.callActivityOnCreate(activity,r.state); //生命週期的OnCreate activity.performStart(); //生命週期的OnStart return activity
-
handleResumeActivity:
-> r.activity.performResume() -> mInstrumentation.callActivityOnResume(this); -> activity.onResume()
相關視訊推薦
【安卓面試合集】startActivity面試點01
Android(安卓)開發零基礎從入門到精通
本文轉自 https://juejin.cn/post/6844904058688372750,如有侵權,請聯絡刪除。