前言
? 我還記得上個學(xué)期意外看到一篇文章,是凱子哥的一篇博客模叙,講的是app第一個activity啟動的底層過程(java)薄坏,我當時幾乎沒接觸過這塊的源碼侵浸,好像看了一半就放棄。還有一次刷知乎础嫡,看到一個人回答為什么ActivityThread里面Loop不會造成ANR杭跪,但是也是一臉萌比。這個學(xué)期開始刷藝術(shù)探索驰吓,已經(jīng)看完了第十章涧尿,每一章都對著源碼自己又看了一遍,再加上之前對Binder,IPC的淺顯的研究檬贰。今天重新再來看這篇文章[【凱子哥帶你學(xué)Framework】Activity啟動過程全解析]姑廉,發(fā)現(xiàn)基本上是看小說一樣的輕松看完了。翁涤。這是一種進步G叛浴!感覺挺好的葵礼。感謝大神的知識分享号阿,下面我用自己的方式來總結(jié)一下Activity啟動的過程,但是我跟凱子哥不同鸳粉,他講的那個其實就多了一點Launcher和applicaiton創(chuàng)建的知識扔涧。
? 說一點自己的學(xué)習(xí)感受。首先:
- 源碼海洋里面不要太追求了解每一個細節(jié)届谈,不然分分鐘迷失自我枯夜。
- 有些知識是需要有其他知識儲備才能理解的。所以看不懂的時候放一放艰山,過一段時間再來看湖雹。比如binder設(shè)計原理那塊我就留了一半。曙搬。因為后半部分有點看不太懂了摔吏,涉及到了C草。
- 看書上的源碼遠遠不夠纵装,一定一定要自己去獨立的看一遍征讲,自己去把整個流程過一遍。
- 畫草圖搂擦,流程圖稳诚。因為過程異常的復(fù)雜,在不同的類里面調(diào)來調(diào)用瀑踢,又臭又長的調(diào)用鏈扳还。
- 永遠不要放棄才避,靜下心來研究,一切都不是問題氨距。
知識儲備
Binder, IPC機制桑逝。可以看看我之前的兩篇文章Android-IPC系列(一)Android-IPC系列(二) 俏让。還有幾篇我覺得寫的非常好的文章Android Binder設(shè)計與實現(xiàn) - 設(shè)計篇 Android進程間通信(IPC)機制Binder簡要介紹和學(xué)習(xí)計劃 楞遏。(這兩篇講的都比較深)看到藝術(shù)探索后面我終于知道為什么binder要在第二章就講解了。因為Binder在后面幾乎是無處不在首昔!
ActivityManagerService寡喝。本質(zhì)就是一個Binder,并且實體在服務(wù)端勒奇。AMS在遠端操作著activity的生命周期预鬓。這個進程由SystemServer進程fork出來。
ActivityThread赊颠。大家都知道ActivityThread就是應(yīng)用的UI線程格二,main方法就是整個應(yīng)用的入口。ActivityThread本質(zhì)并不是一個線程竣蹦,他只是依附著主線程存在顶猜。ActivityThread通過和AMS進行IPC通信來共同管理Activity的生命周期。在后面我準備寫一篇關(guān)于Handle的續(xù)篇痘括,里面還會提到他长窄,因為主線程里面的Looper就是在這里init的。
ApplicationThread.远寸。它是ActivityThread的內(nèi)部類抄淑,本質(zhì)上ActivityThread是通過它來進行和AMS的IPC通信的。它的本質(zhì)也是一個Binder驰后!只不過這次他的實體放在客戶端,AMS通過他的代理類ApplicationThreadProxy來和ApplicationThread通信矗愧。
Instrumentation.灶芝。這個類我在看完第一遍書的時候感覺操作調(diào)用鏈里面的最外層。因為最后一步Activity實例對象的生成和onCreat()方法的調(diào)用最終是來自這個類的唉韭。其實這個類是ActivityThread想要進行的操作的具體操作類夜涕。這個類是全局的,并且每個acitivity里面都擁有一個它的引用属愤。
ActivityStack(AMS中)女器。很好懂,一個activity棧住诸。但是這個ActivityStack是有兩種類型的驾胆,一種叫系統(tǒng)ActivityStack(HomeTask),這一類的ActivityStack包含著Launcher(或者有其他我不知道的)涣澡,還有一種是普通應(yīng)用的ActivityStack(安卓中Task這個概念的具體實現(xiàn)形式),其實就是一個Task(任務(wù)棧)丧诺。這個類是由AMS來管理入桂,AMS通過這個數(shù)據(jù)結(jié)構(gòu)來得知activity的狀態(tài)。
ActivityStackSuperisor(AMS中)驳阎。加了一個單詞抗愁,就是activity棧的管理者。這個類的作用就是管理棧呵晚,并且通過ActivityStack來獲得要啟動的activity的信息蜘腌。
ActivityRecord。這個就是上面說的服務(wù)端的actiivty信息的載體類饵隙。并且也是服務(wù)端的類~這個類相當?shù)闹匾橹椋允贾两K都貫穿在調(diào)用鏈里面,在安卓ActivityStack里面存儲的并不是activity實例癞季,其實就是這個ActivityRecord的實例劫瞳。
ActivityClientRecord。這個和上面區(qū)別就是這個類是客戶端activity信息的載體類绷柒。
-
TaskRecord志于。同樣,這個類就是ActivityTask的信息記錄類而已废睦。
?好了伺绽,我覺得需要好好了解的幾個最核心的類就是這幾個了,大家若不清楚嗜湃,可以自己去源碼里面看奈应,如果我有說錯的也請原諒。购披。杖挣。其實還有很多概念我在binder那篇文章里面講的不少了!這里算是又一次的補充吧刚陡。
Activity啟動的流程
? 源碼之旅開始惩妇。科科.
1.Activity.startActivity(Intent intent)這個我們天天都在寫筐乳,好歌殃,去看源碼!
@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);
}
}
嗯蝙云,繼續(xù)看startActivityForResult()氓皱;
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());
}
...省略代碼
}
直接調(diào)用了Instrumentation去調(diào)用execStartActivity()方法。后面的調(diào)用先不管,直接去看execStartActivity()方法波材。需要注意的是mMainThread.getApplicationThread()就是通過ActivityThread去獲得了一個ApplicaitonThread實例
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
...省略代碼
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
//通過AMS啟動了
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
//用來檢測這個activity啟動的結(jié)果股淡,具體可以去查看源碼
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
看到這里發(fā)現(xiàn)它又用了個什么玩意調(diào)用了startActivity()方法,這是什么呢各聘?這里的ActivityManagerNative.getDefault()就是我們期待了很久的ActivityManagerService的代理類揣非!如果你很清楚Binder的實現(xiàn),這個應(yīng)該難不倒你吧躲因!AMS和代理類本質(zhì)上都是IActivityManager的實現(xiàn)類早敬。(IAcitivtyManager,其實就是一個AIDL接口,不信自己去看源碼)大脉。我給你看看getDefault()方法的實現(xiàn):
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ù)看AMS中startActivity()方法的實現(xiàn)了:注意琐驴,從這里開始,調(diào)用鏈會變得很復(fù)雜
@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) {
//調(diào)用了startActivityAsUser,caller是我們的ApplicaitonThread
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
UserHandle.getCallingUserId());
}
繼續(xù)看這個startActivityAsUser()方法:
@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.轉(zhuǎn)換app里面的activity棧,caller是我們的ApplicaitonThread
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, options, userId, null, null);
}
? 發(fā)現(xiàn)調(diào)用了之前提到的ActivityStackSupervisor的startActivityMayWait()方法秤标。這里的目的就是想去通過棧的管理者來通過傳進來的數(shù)據(jù)去改變棧绝淡,并且拿到被啟動activity的ActivityRecord實例。
? 在startActivityMayWait()里面苍姜,主要做了ActivityStack牢酵, ActivityInfo, LaunchMode等等各種信息的初始化工作,然后就又調(diào)用了startActivityLocked()方法衙猪, 這個方法里面又做了一系列的變量初始化馍乙,初始啟動的錯誤判斷, uid檢查之后,又調(diào)用了startActivityUncheckedLocked()方法垫释。這個方法里面根據(jù)前面一系列的工作丝格,確定了最終的LanuchMode,這個LaunchMode會在后面的函數(shù)被拿來進行判斷,構(gòu)建了一個新的intent棵譬,ActivityInfo,ActivityTask显蝌。反正過程都TM又臭又長,細看下去一天就耗完了订咸。接下來我們可以看到最終調(diào)用targetStack.resumeTopActivityLocked()方法琅束。這個targetStack就是新的activity所要放入的Task的位置。也就是說算谈,現(xiàn)在又要轉(zhuǎn)到ActivityTask中去看源碼了,科科料滥!
? 注意的是然眼,LaunchMode和ActivityStack的選擇是個很復(fù)雜的過程。我推薦一篇文章以及安卓的官方文檔鏈接葵腹。官方文檔,頓文的博客
? 需要非常注意的是高每,這個函數(shù)執(zhí)行的時候屿岂,被啟動的activity里面被添加到棧里面去了,top鲸匿,next就是指代這個要被啟動的activity爷怀。pre,current就是指代當前resumed的activity。你別弄混了带欢,雖然這個問題我TM看了一整天的源碼运授。注意,被啟動的activity雖然還沒有被實例乔煞,但是它的ActivityRecord實例已經(jīng)被構(gòu)建出來了吁朦,并且已經(jīng)被添加到stack里面去了。具體的調(diào)用過程是:
? Supervisor.setActivityUnchekedLocked->resumeTopActivityLocked(這里是ActivityStackSuperbisor里面的方法)->ActivityStack.startActivityLocked在這里將activity添加到stack里面渡贾。并且在之后才會調(diào)用ActivityStack的resumeTopActivityLocked方法
/**
* Ensure that the top activity in the stack is resumed.
*
* @param prev The previously resumed activity, for when in the process
* of pausing; can be null to call from elsewhere.
*
* @return Returns true if something is being resumed, or false if
* nothing happened.
*/
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
if (inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
inResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
} finally {
inResumeTopActivity = false;
}
return result;
}
?
? 不要有情緒逗宜,繼續(xù)看resumeTopActivityInnerLocked(prev, options);這個方法太長了,我分析了一整天空骚,終于所有體會吧纺讲。這個方法最終的作用是將啟動者activity的生命周期變成paused,這樣之后被啟動的activity的實例創(chuàng)建了之后才能順利的resumed囤屹。我們來看部分代碼:
// Find the first activity that is not finishing.
//找出棧頂中第一個沒有在被finish的activity,既我們要啟動的actiivty
ActivityRecord next = topRunningActivityLocked(null);
// 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;
final TaskRecord prevTask = prev != null ? prev.task : null;
//如果整個stack里面是空的熬甚,那么直接啟動launcher
if (next == null) {
// There are no more activities! Let's just start up the
// Launcher...
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
// Only resume home if on home display
final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
//直接resume系統(tǒng)ActivityStack里面的根activity(Launcher)
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
}
? 在這里,next這個變量很關(guān)鍵牺丙。它的注釋說的是第一個沒有正在被銷毀的activity则涯,顯然我們要被啟動的activity符合這個條件。并且如果這個應(yīng)用級別的stack是空的冲簿,也就是說現(xiàn)在應(yīng)該跳轉(zhuǎn)到系統(tǒng)級別的stack去粟判,也就是顯示系統(tǒng)桌面。
// If the top activity is the resumed one, nothing to do.
//如果被啟動的activity就是當前處理Resumed狀態(tài)的activity的話峦剔,就什么不做档礁。(一個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.
mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Top activity resumed " + next);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
// Make sure to notify Keyguard as well if it is waiting for an activity to be drawn.
mStackSupervisor.notifyActivityDrawnForKeyguard();
return false;
}
?
? 我注釋說的很清楚了,如果要啟動的activity已經(jīng)是resumed了吝沫,就什么都不做呻澜。因為這就是一個當前resumed的activity啟動它自己。
// If we are sleeping, and there is no resumed activity, and the top
// activity is paused, well that is the state we want.
//如果系統(tǒng)正在休眠惨险,并且當前最上層的activity都已經(jīng)是paused狀態(tài)了(top activity就是我們要啟動的activity)羹幸。那就是完美的狀態(tài)。
if (mService.isSleepingOrShuttingDown()
&& mLastPausedActivity == next
&& mStackSupervisor.allPausedActivitiesComplete()) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Going to sleep and all paused");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
? 如果系統(tǒng)正在休眠辫愉,并且當前最上層的activity都已經(jīng)是paused狀態(tài)了(top activity就是我們要啟動的activity)栅受。那就是完美的狀態(tài)。
// 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,
/ "resumeTopActivityLocked: Skip resume: some activity pausing.");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
? 如果我們的app里面正在暫停某個activity,那么我們什么都不要做等這個做完屏镊,因為暫停activity的過程是串行的依疼,必須要一個一個按順序的來。不能同時來而芥,我認為原因就是因為客戶端調(diào)用遠程服務(wù)的過程的時候本地的客戶端所在線程會被掛起
/ We need to start pausing the current activity so the top one
// can be resumed...
//先把現(xiàn)在的當前還是resumed的activity pause了律罢,這樣新加進來的activity才能resume」髫ぃ基礎(chǔ)知識
boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
//開始暫定現(xiàn)在stack里面所有的activity
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
if (mResumedActivity != null) {
//開始pausing當前的所有activity误辑,并且返回一個是否暫定成功的結(jié)果回來
pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
}
? 這里就是在做把當前啟動者activity給pause掉,即至于為什么要這么做骄酗。稀余。不用我多說了吧。
? startPausingLocked(userLeaving, false, true, dontWaitForPause);這個函數(shù)跟著看下去就是通過AMS來暫停activity的過程趋翻。這個就不多說了睛琳,大同小異。
最終在函數(shù)的末尾會又調(diào)用ActivityStackSupervisor的startSpecificActivityLocked(next, true, true);方法踏烙。這個方法的源碼如下:
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
//注意了师骗,這里的app之后會用到,因為app.thread就是獲得了applicationthread實例讨惩!
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);
}
//將app辟癌,信息完整的要啟動的ActivityRecord類的實例傳到另一個方法里面去
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ù)跟進這個realStartActivityLocked()(真正啟動activity的過程在這里):
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
r.startFreezingScreenLocked(app, 0);
if (false) Slog.d(TAG, "realStartActivity: setting app visibility true");
mWindowManager.setAppVisibility(r.appToken, true);
// schedule launch ticks to collect information about slow apps.
r.startLaunchTickingLocked();
// Have the window manager re-evaluate the orientation of
// the screen based on the new activity order. Note that
// as a result of this, it can call back into the activity
// manager with a new orientation. We don't care about that,
// because the activity is not currently running so we are
// just restarting it anyway.
if (checkConfig) {
Configuration config = mWindowManager.updateOrientationFromAppTokens(
mService.mConfiguration,
r.mayFreezeScreenLocked(app) ? r.appToken : null);
mService.updateConfigurationLocked(config, r, false, false);
}
r.app = app;
app.waitingToKill = null;
r.launchCount++;
r.lastLaunchTime = SystemClock.uptimeMillis();
if (localLOGV) Slog.v(TAG, "Launching: " + r);
int idx = app.activities.indexOf(r);
if (idx < 0) {
app.activities.add(r);
}
mService.updateLruProcessLocked(app, true, null);
mService.updateOomAdjLocked();
final ActivityStack stack = r.task.stack;
try {
if (app.thread == null) {
throw new RemoteException();
}
List<ResultInfo> results = null;
List<Intent> newIntents = null;
if (andResume) {
results = r.results;
newIntents = r.newIntents;
}
...省略代碼
//通過applicaitonthread調(diào)用客戶端binder實體的方法。
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
r.compat, r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState,
results, newIntents, !andResume, mService.isNextTransitionForward(),
profilerInfo);
...省略代碼
return true;
}
? 這里面兩個很重要的參數(shù)荐捻,一個是ActivityRecord黍少,一個是app。前者就是在ActivityStack里面轉(zhuǎn)了一圈之后得出來的最終要啟動的Activity的信息記錄類处面。后者就是用來獲得ApplicationThread來通知客戶端拿這個ActivityRecord去管理你的activity的生命周期吧厂置!相當于AMS給了ActivityThread一個任務(wù),讓后者去執(zhí)行魂角。同樣昵济,這也是一個IPC的過程。最終調(diào)用鏈繞了好大一圈終于又回到了ApplicaitonThread野揪。
? 值得一提的是访忿,凡是schedule開頭的函數(shù)都是通過handler來做線程調(diào)度的,不服來辯斯稳。我們點進去
public final void scheduleResumeActivity(IBinder token, int processState,
boolean isForward, Bundle resumeArgs) {
updateProcessState(processState, false);
sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
}
? 果然用handler發(fā)送了一個message海铆。我們來看handler的處理會最終調(diào)用handlerLaunchActivity方法:
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
? 可以看到activity的實例是由performLaunchActivity方法生成的。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
//獲得一些基本信息
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
//通過Instrumentation利用類加載器來生成一個activity實例
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
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);
}
}
//嘗試生成application
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
//創(chuàng)建contextImpl對象挣惰,并且調(diào)用activity的attach()方法來進行一些activity初始化
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
//設(shè)置activity的theme
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 {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
mActivities.put(r.token, r);
return activity;
}
? 做了這些事情
- 從ActivityClientRecord中獲取獲取組件信息
- 通過Instrumentation創(chuàng)建Activity對象
- 通過LoadApk的makeApplication創(chuàng)建application游添,這個方法有興趣自己去看系草,就是一個單例而已。
- 創(chuàng)建contextImpl對象唆涝,并且調(diào)用activity的attach()方法來進行一些activity初始化
- 調(diào)用activity的onCreat()方法
完成整個過程調(diào)用 !4奖妗@群ā!
結(jié)束語
? 系統(tǒng)源碼看起來確實感覺自己置身茫茫大海一樣赏枚,特別是要去找一些不理解的問題的時候亡驰。比如到底是被啟動的activity的ActivityRecord實例先添加進去還是在實例創(chuàng)建了之后才添加進去,這個問題我看源碼著了一天才還沒有什么結(jié)果饿幅,后來在別人的幫助和查閱老羅的資料才找到問題所在凡辱。挺不錯的一次過程,確實細節(jié)不必死扣栗恩,但是有些基本問題不懂的話還是應(yīng)該去探究一下透乾。
版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載磕秤。