系列文章:
前言
接觸過Android開發(fā)的同學(xué)都知道Activity,Activity作為Android四大組件之一,使用頻率高。簡單來說Activity提供了一個(gè)顯示界面,讓用戶進(jìn)行各種操作,本文主要分為以下三個(gè)部分:Activity的生命周期,啟動(dòng)模式,以及Activity的工作過程。文中大部分篇幅來自《Android開發(fā)藝術(shù)探索》一書,盡管想多以流程或圖片的形式說明,奈何文筆有限,Android系統(tǒng)整體把握還不夠深入,只能借鑒參考前輩的成果,本文主要目的是幫自己梳理Activity的相關(guān)問題,疏漏之處歡迎指出。
說明:本文中的源碼都是基于Android-25版本。
Activity生命周期
生命周期
首先給出Activity的完整生命周期,如下圖所示:
圖片來源Android開發(fā)者官網(wǎng)
看完了完整的生命周期,我們再分別簡單介紹單個(gè)生命周期含義。
-
onCreate
:表示Activity正在被創(chuàng)建,做一些初始化工作,如加載布局文件,對一些變量或者控件進(jìn)行初始化 -
onStart
:表示Activity正在啟動(dòng),此時(shí)Activity已經(jīng)可見了,但還無法和用戶交互 -
onResume
:表示Activity已經(jīng)在前臺(tái),可以和用戶交互了 -
onPause
:表示Activity正在停止,此時(shí)可以進(jìn)行一些輕量級的存儲(chǔ)數(shù)據(jù)和停止動(dòng)畫等工作,但不能太耗時(shí),否則會(huì)影響到新Activity的顯示,Android指定如果onPause
在500ms內(nèi)沒有執(zhí)行完畢的話就會(huì)強(qiáng)制關(guān)閉Activity。某些極端情況下,這個(gè)時(shí)候Activity會(huì)回到當(dāng)前Activity,此時(shí)onResume
會(huì)被執(zhí)行,很難重現(xiàn)這一情形 -
onStop
:表示Activity即將停止,此時(shí)Activity已經(jīng)不可見了,但是Activity對象還存在內(nèi)存中,沒有被銷毀,這個(gè)階段也主要做一些資源回收的工作,不能太耗時(shí) -
onDestory
:表示Activity即將被銷毀,可以做一些回收工作和最終的資源釋放,最后一個(gè)回調(diào)方法 -
onRestart
:表示Activity重新啟動(dòng),當(dāng)前Activity從不可見重新變?yōu)榭梢姇r(shí)會(huì)調(diào)用onRestart
,這種情況一般是用戶的行為導(dǎo)致的,比如:用戶按Home鍵切換到桌面或者打開了一個(gè)新的Activity
三個(gè)問題
onCreate,onStart和onResume之間的區(qū)別?
-
onCreate
時(shí)Activity還不可見,onStart
已經(jīng)可見,還不在前臺(tái),onResume
已經(jīng)出現(xiàn)在前臺(tái) -
onCreate
方法只在Activity創(chuàng)建時(shí)執(zhí)行一次,而onStart
方法在Activity的切換以及按Home鍵返回桌面再切回應(yīng)用的過程中被多次調(diào)用,因此數(shù)據(jù)恢復(fù)在onStart
方法中比較合適,onResume
方法可以做一些開啟動(dòng)畫和獨(dú)占設(shè)備的操作
onPause,onStop和onDestroy之間的區(qū)別?
-
onPause
時(shí)Activity還可見,onStop
已經(jīng)不可見,但Activity對象還存在內(nèi)存中,onDestroy
后Activity對象就不存在了 - 內(nèi)存不足時(shí),可能不會(huì)執(zhí)行
onStop
方法,因此程序狀態(tài)保存,停止動(dòng)畫,存儲(chǔ)數(shù)據(jù)等操作最好放在onPause
中
切換Activity時(shí)生命周期執(zhí)行順序
假設(shè)當(dāng)前Activity為A,此時(shí)用戶打開Activity B,那么A和B的生命周期的執(zhí)行順序?yàn)椋?/p>
為了驗(yàn)證生命周期執(zhí)行順序,我們寫個(gè)例子實(shí)測,MainActivity
中單擊按鈕跳轉(zhuǎn)到SecondActivity
,然后在相應(yīng)的生命周期中輸出日志,如下:
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
...
@Override
protected void onPause(){
super.onPause();
Log.d(TAG,"onPause");
}
@Override
protected void onStop(){
super.onStop();
Log.d(TAG,"onStop");
}
}
public class SecondActivity extends Activity {
private static final String TAG = "SecondActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG,"onCreate");
}
@Override
protected void onStart(){
super.onStart();
Log.d(TAG,"onStart");
}
@Override
protected void onResume(){
super.onResume();
Log.d(TAG,"onResume");
}
}
日志結(jié)果如下:
08-31 12:36:36.086 3825-3825/com.sht.user.activityjumptest D/MainActivity: onPause
08-31 12:36:36.093 3825-3825/com.sht.user.activityjumptest D/SecondActivity: onCreate
08-31 12:36:36.093 3825-3825/com.sht.user.activityjumptest D/SecondActivity: onStart
08-31 12:36:36.094 3825-3825/com.sht.user.activityjumptest D/SecondActivity: onResume
08-31 12:36:36.517 3825-3825/com.sht.user.activityjumptest D/MainActivity: onStop
那么為什么會(huì)有這樣的生命周期執(zhí)行順序呢?Android官方文檔對onPause的解釋為:不能在onPause中做重量級的操作,因?yàn)楸仨歰nPause執(zhí)行完成以后新Activity才能Resume
,同時(shí)我在分析Activity啟動(dòng)源過程中碼也得到了相同結(jié)論。
Activity保存狀態(tài)
當(dāng) Activity 暫停或停止時(shí),Activity 的狀態(tài)會(huì)得到保留。因?yàn)楫?dāng) Activity 暫停或停止時(shí),Activity 對象仍保留在內(nèi)存中 ,有關(guān)其成員和當(dāng)前狀態(tài)的所有信息仍處于活動(dòng)狀態(tài)。
但是當(dāng)系統(tǒng)的配置發(fā)生變化(屏幕旋轉(zhuǎn),語言變換等)時(shí),Activity 被銷毀,系統(tǒng)回調(diào) onSaveInstanceState()
方法對有關(guān) Activity 狀態(tài)的信息進(jìn)行保存,系統(tǒng)會(huì)向該方法傳遞一個(gè) Bundle
,可以在其中使用 putString()
和 putInt()
等方法以名稱-值對
形式保存有關(guān) Activity 狀態(tài)的信息。當(dāng) Activity 重建時(shí)將 Bundle
同時(shí)傳遞給 onCreate()
和 onRestoreInstanceState()
方法,使用上述任一方法從 Bundle
提取保存的數(shù)據(jù)并恢復(fù)該 Activity 狀態(tài)。
圖片來源Android開發(fā)者官網(wǎng)
在 onSaveInstanceState()
和 onRestoreInstanceState()
方法中,系統(tǒng)自動(dòng)為我們做了一定的恢復(fù)工作,布局中的每個(gè) View 調(diào)用自己的 onSaveInstanceState()
方法,讓每個(gè)視圖都能保存自身需保存的信息。
每個(gè) View 都有 onSaveInstanceState()
和 onRestoreInstanceState()
方法,具體能恢復(fù)哪些數(shù)據(jù),需要查看其源碼。保存和恢復(fù) View 用到了事件委托思想,從下至上,再從上到下。需要注意的是,只有我們?yōu)?View 指定了唯一的ID屬性(android:id
)系統(tǒng)才會(huì)自動(dòng)為其在需要時(shí)自動(dòng)保存和恢復(fù)數(shù)據(jù)。
通過重寫onSaveInstanceState()
和 onRestoreInstanceState()
實(shí)現(xiàn)自定義的數(shù)據(jù)恢復(fù)機(jī)制。
那么 onSaveInstanceState()
和 onRestoreInstanceState()
方法和 Activity 的生命周期的執(zhí)行順序是怎么樣的?
onSaveInstanceState()
方法是在onStop
之前,和onPause
沒有既定的時(shí)序關(guān)系, onRestoreInstanceState()
方法是在onStart
之后、onResume
之前調(diào)用的。
Activity啟動(dòng)模式
默認(rèn)情況下,當(dāng)我們多次啟動(dòng)同一個(gè)Activity時(shí),系統(tǒng)會(huì)創(chuàng)建多個(gè)實(shí)例并把它們一一放入任務(wù)棧中,任務(wù)棧是一種后進(jìn)先出的棧結(jié)構(gòu),每按下back鍵就會(huì)有一個(gè)Activity出棧,直到棧空為止。
standard:標(biāo)準(zhǔn)模式
這是系統(tǒng)默認(rèn)的模式,每次啟動(dòng)一個(gè)新的Activity都會(huì)重新創(chuàng)建一個(gè)新的實(shí)例,不管這個(gè)實(shí)例已經(jīng)是否存在。這種模式下,如果A啟動(dòng)了B(標(biāo)準(zhǔn)模式),那么B自動(dòng)進(jìn)入A所在的任務(wù)棧中。
singleTop:棧頂復(fù)用模式
此種模式下,如果新Activity已經(jīng)位于任務(wù)棧的棧頂,那么此Activity不會(huì)被重新創(chuàng)建,同時(shí)onNewIntent
方法會(huì)被調(diào)用,通過此方法的參數(shù)獲取當(dāng)前請求信息。而且,此Activity的onCreate,onStart不會(huì)被調(diào)用,因?yàn)闆]有發(fā)生改變。
singleTask:棧內(nèi)復(fù)用模式
此種模式下,只要Activity在一個(gè)棧中存在,那么多次啟動(dòng)此Activity都不會(huì)重新創(chuàng)建實(shí)例,系統(tǒng)會(huì)回調(diào)onNewIntent方法。系統(tǒng)會(huì)先尋找是否存在A想要的任務(wù)棧,如果不存在,就重建一個(gè)任務(wù)棧,然后創(chuàng)建A的實(shí)例放入新任務(wù)棧中;如果存在A想要的任務(wù)棧,再查看是否有Activity實(shí)例存在,有的話就把該實(shí)例調(diào)到棧頂,如果實(shí)例不存在,則創(chuàng)建A的實(shí)例放入任務(wù)棧中。下面舉三種例子說明此種模式運(yùn)行機(jī)制:
- 目前任務(wù)棧S1中為ABC,Activity D以
singleTask
模式請求啟動(dòng),其需要的任務(wù)棧為S1,那么系統(tǒng)會(huì)創(chuàng)建D的實(shí)例,將D放入S1中 - 目前任務(wù)棧S1中為ABC,Activity D以
singleTask
模式請求啟動(dòng),其需要的任務(wù)棧為S2,那么系統(tǒng)會(huì)創(chuàng)建任務(wù)棧S2,再將D放入S2中 - 目前任務(wù)棧S1中為ADBC,Activity D以
singleTask
模式請求啟動(dòng),其需要的任務(wù)棧為S1,那么系統(tǒng)不會(huì)創(chuàng)建D的實(shí)例,將D切換到棧頂并調(diào)用其onNewIntent
方法,同時(shí)棧內(nèi)所有在D上面的Activity都需要出棧,最終的S1為AD
singleInstance:單實(shí)例模式
這是一種加強(qiáng)的singleTask
模式,除了具有singleTask模式的所有特性外,具有此種模式的Activity只能單獨(dú)位于一個(gè)任務(wù)棧中。比如Activity A以singleInstance
模式啟動(dòng),系統(tǒng)會(huì)為其創(chuàng)建一個(gè)新的任務(wù)棧,然后A獨(dú)自運(yùn)行在該任務(wù)棧中,后續(xù)的請求均不會(huì)創(chuàng)建新的Activity。
任務(wù)棧
在啟動(dòng)模式中多次提到Activity的任務(wù)棧,默認(rèn)情況下,所有Activity所需任務(wù)棧的名字為應(yīng)用的包名。此外還有一個(gè)參數(shù)TaskAffinity
,這個(gè)參數(shù)標(biāo)識(shí)了Activity所需要的任務(wù)棧的名字,TaskAffinity
屬性主要和singleTask
模式或者allowTaskReparenting
屬性配對使用,具體請參考《Android開發(fā)藝術(shù)探索》P19
和Android任務(wù)和返回棧完全解析,細(xì)數(shù)那些你所不知道的細(xì)節(jié)。
如何指定Activity啟動(dòng)模式
- 第一種是通過AndroidManifest.xml 指定:
<activity android:name=".SecondActivity"
android:launchMode="singleTask"
android:label="@string/app_name"/>
- 第二種是通過在Intent中設(shè)置標(biāo)志位,比如:
Intent intent = new Intent();
intent.setClass(MainActivity.this, SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Activity啟動(dòng)過程源碼分析
聊完了Activity的生命周期及啟動(dòng)模式,最頭疼的部分來了,那就是一個(gè)Activity究竟是如何啟動(dòng)的呢?以下篇幅結(jié)合源碼一探究竟,撥開云霧見青天。在顯式調(diào)用啟動(dòng)Activity時(shí),我們通過以下代碼完成:
Intent intent = new Intent(this, TestActivity.class);
startActivity(intent);
上述代碼便可以啟動(dòng)一個(gè)Activity,下面我們便從源頭理清Activity的啟動(dòng)流程,當(dāng)然我們不可能對所有細(xì)節(jié)描述清楚,需要做的是理清流程,點(diǎn)到為止。
startActivity/startActivityForResult
我們從Activity的startActivity
方法開始分析,讀源碼可知,startActivity
方法有好幾種重載形式,但最終都調(diào)用了startActivityForResult
方法,因此我們重點(diǎn)分析startActivityForResult
方法:
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
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);
}
}
}
Instrumentation
我們主要關(guān)注mParent == null
這一部分邏輯,首先,mParent
是一個(gè)Activity對象,表示該Activity是否由父Activity啟動(dòng),如果該Activity是第一個(gè)被啟動(dòng)的,那么就會(huì)調(diào)用Instrumentation
的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(who);
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
// 檢查啟動(dòng)Activity的結(jié)果
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
Instrumentation
是管理Activity的一個(gè)工具類,包括創(chuàng)建和啟動(dòng)Activity,Activity的生命周期方法都是由Instrumentation
這個(gè)類來控制,一個(gè)進(jìn)程中只用一個(gè)Instrumentation
實(shí)例。
execStartActivity
是真正啟動(dòng)Activity的操作,下面解釋其參數(shù):
- who : 待啟動(dòng)的Activity對象
- mMainThread.getApplicationThread() : ApplicationThread對象,也是Binder對象
- mToken :Binder對象,指向服務(wù)端一個(gè)ActivityRecord對象
- target :待啟動(dòng)的Activity對象
- intent :啟動(dòng)的intent對象
- requestCode :請求碼
- options :參數(shù)
AMS
再回到execStartActivity
方法體中,其中可以看到真正實(shí)現(xiàn)Activity啟動(dòng)的是ActivityManagerNative.getDefault().startActivity
方法。下面列出了ActivityManagerNative.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;
}
};
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in; // 同一進(jìn)程,返回本地對象stub
}
return new ActivityManagerProxy(obj); // 跨進(jìn)程,返回代理對象
}
其中聲明了一個(gè)Singleton
封裝類,類型是IActivityManager
,第一次調(diào)用它的get方法它會(huì)通過create
方法來初始化AMS
這個(gè)Binder
對象。其中在asInterface
方法中返回了一個(gè)IActivityManager
類型對象。
ActivityManagerService(AMS)
繼承自ActivityManagerNative
,而ActivityManagerNative
繼承自Binder
并實(shí)現(xiàn)了IActivityManager
接口,因此AMS
是一個(gè)Binder
,同時(shí)也是IActivityManager
的具體實(shí)現(xiàn),ActivityManagerNative.getDefault()
其實(shí)是一個(gè)IActivityManager
類型的Binder
對象,即AMS
。我們理一下上面提到的各種類和接口之間的關(guān)系:
public final class ActivityManagerService extends ActivityManagerNative {...}
public abstract class ActivityManagerNative extends Binder implements IActivityManager {...}
public interface IActivityManager extends IInterface {...}
所以Activity的啟動(dòng)過程轉(zhuǎn)移到AMS
中,下面分析AMS
的startActivity
方法:
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "startActivity", null);
// Android7.0 Acitivty啟動(dòng)管理類新增ActivityStarter(原本是ActivityStackSupervisor處理該過程)
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null);
}
ActivityStarter
上述代碼中mActivityStarter
是一個(gè)ActivityStarter
對象,初始化為:
mActivityStarter = new ActivityStarter(this, mStackSupervisor);
可以看出Activity的啟動(dòng)過程轉(zhuǎn)移到ActivityStarter
的startActivityMayWait
方法中,startActivityMayWait
又調(diào)用了startActivityLocked
方法:
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, IActivityManager.WaitResult outResult, Configuration config,
Bundle bOptions, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask) {
...
// 根據(jù)Intent中在系統(tǒng)中找到合適的應(yīng)用的Activity,如果有多個(gè)Activity可選擇則彈出界面讓用戶選擇
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
...
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor,
resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, outRecord, container,
inTask);
...
return res;
}
}
startActivityLocked
方法又調(diào)用startActivityUnchecked
方法:
final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
...
// 創(chuàng)建ActivityRecord對象
// ActivityRecord : 在AMS中,用ActivityRecord來作為Activity的記錄者,每次啟動(dòng)一個(gè)Actvity會(huì)有一個(gè)對應(yīng)
// 的ActivityRecord對象,表示Activity的一個(gè)記錄
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
options, sourceRecord);
...
err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true, options, inTask);
...
// 此處Activity對應(yīng)的Task被移至前臺(tái)
postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
return err;
}
startActivityUnchecked
調(diào)用了ActivityStack
的startActivityLocked
方法和ActivityStackSupervisor
的resumeFocusedStackTopActivityLocked
方法:
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
...
// ActivityStack的startActivityLocked方法
mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
if (mDoResume) {
final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
// If the activity is not focusable, we can't resume it, but still would like to
// make sure it becomes visible as it starts (this will also trigger entry
// animation). An example of this are PIP activities.
// Also, we don't want to resume activities in a task that currently has an overlay
// as the starting activity just needs to be in the visible paused state until the
// over is removed.
} else {
// ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,mOptions);
}
...
}
...
}
ActivityStackSupervisor
ActivityStackSupervisor
的resumeFocusedStackTopActivityLocked
方法如下:
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (targetStack != null && isFocusedStack(targetStack)) {
// 待啟動(dòng)Activity對應(yīng)的Task為前臺(tái)棧時(shí),調(diào)用該Task對應(yīng)ActivityStack的resumeTopActivityUncheckedLocked方法
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || r.state != RESUMED) {
// 否則只是調(diào)用此時(shí)前臺(tái)棧的resumeTopActivityUncheckedLocked方法
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
}
return false;
}
ActivityStack
下面進(jìn)入ActivityStack
的resumeTopActivityUncheckedLocked
方法:
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
...
result = resumeTopActivityInnerLocked(prev, options);
...
return result;
}
緊接著又調(diào)用了resumeTopActivityInnerLocked
方法:
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...
// mResumedActivity指向上一次啟動(dòng)的Activity
if (mResumedActivity != null) {
...
// 讓上一次的Activity進(jìn)入pause狀態(tài)
pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause);
}
if (pausing) {
...
if (next.app != null && next.app.thread != null) {
// 如果Activity所在App已經(jīng)啟動(dòng),則更新Activity所在進(jìn)程優(yōu)先級,防止被kill
mService.updateLruProcessLocked(next.app, true, null);
}
...
}
...
if (next.app != null && next.app.thread != null) {
...
if (next.newIntents != null) {
// 如果Intent不為空,則調(diào)用NewIntent傳入Intent參數(shù)
next.app.thread.scheduleNewIntent(
next.newIntents, next.appToken, false /* andPause */);
...
}
...
// Activity已經(jīng)啟動(dòng),重新進(jìn)入前臺(tái)
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
mService.isNextTransitionForward(), resumeAnimOptions);
...
} else {
...
// 創(chuàng)建進(jìn)程,啟動(dòng)Activity,或者已經(jīng)啟動(dòng)App,啟動(dòng)Activity
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
...
return true;
}
resumeTopActivityInnerLocked
方法又調(diào)用了ActivityStackSupervisor
的startSpecificActivityLocked
方法:
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);
}
// 目標(biāo)Activity所在APP已啟動(dòng)
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.
}
// 目標(biāo)Activity所在APP未啟動(dòng),通過zygote創(chuàng)建應(yīng)用進(jìn)程
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
startSpecificActivityLocked
方法調(diào)用了realStartActivityLocked
方法:
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
...
// 目標(biāo)Activity所在APP已啟動(dòng),通過此方法啟動(dòng)目標(biāo)Activity
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
...
}
上面這段代碼中,其中app.thread
的類型是IApplicationThread
,IApplicationThread
的聲明如下:
public interface IApplicationThread extends IInterface {...}
IApplicationThread
繼承了IInterface
,所以它是一個(gè)Binder
類型的接口,IApplicationThread
內(nèi)部包含了大量啟動(dòng)、停止Activity的接口,此外還包含啟動(dòng)和停止服務(wù)的接口。
IApplicationThread
的實(shí)現(xiàn)者就是ActivityThread
的內(nèi)部類ApplicationThread
,相關(guān)類的繼承和實(shí)現(xiàn)關(guān)系如下所示:
private class ApplicationThread extends ApplicationThreadNative { ... }
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread { ... }
說了這么多,分析下來不僅累,還容易被繞暈,畫張流程圖總結(jié)下:
ApplicationThread
繞了一圈,Activity的啟動(dòng)過程還是回到了ApplicationThread
中,ApplicationThread
通過scheduleLaunchActivity
方法啟動(dòng)Activity,源碼如下:
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);
}
其主要實(shí)現(xiàn)就是發(fā)送一個(gè)啟動(dòng)消息交由Handler處理,這個(gè)Handler有個(gè)特殊的名字叫H
(是不是很萌的名字),sendMessage
的實(shí)現(xiàn)如下:
private void sendMessage(int what, Object obj, int arg1, int arg2, int seq) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + mH.codeToString(what) + " arg1=" + arg1 + " arg2=" + arg2 +
"seq= " + seq);
Message msg = Message.obtain();
msg.what = what;
SomeArgs args = SomeArgs.obtain();
args.arg1 = obj;
args.argi1 = arg1;
args.argi2 = arg2;
args.argi3 = seq;
msg.obj = args;
mH.sendMessage(msg);
}
H
對Activity啟動(dòng)的消息進(jìn)行處理:
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);
}
break;
ActivityThread
從上面代碼可以看出,Activity的啟動(dòng)過程又轉(zhuǎn)到ActivityThread
的handleLaunchActivity
方法中,其源碼如下:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
...
// 此方法中完成Activity生命周期的onCreate和onStart方法
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
// 此方法中完成Activity生命周期的onResume方法
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
...
}
...
}
上述代碼中的performLaunchActivity
方法最終完成了Activity對象的創(chuàng)建和啟動(dòng)過程,performLaunchActivity
這個(gè)方法主要完成了以下幾件事:
摘自Android開發(fā)藝術(shù)探索
- 從ActivityClientRecord中獲取待啟動(dòng)的Activity的組件信息
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
// ComponentName用來定義一個(gè)應(yīng)用程序組件,例如Activity,Service,BroadcastReceiver,ContentProvider
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的newActivity方法使用類加載器創(chuàng)建Activity對象
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
// 通過類加載器來創(chuàng)建Activity對象
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);
}
}
- 通過LoadedApk的makeApplication方法來創(chuàng)建Application對象
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
// 先判斷Application是否為空,如果Application被創(chuàng)建過,就不會(huì)再重復(fù)創(chuàng)建,一個(gè)應(yīng)用只有一個(gè)Application對象
if (mApplication != null) {
return mApplication;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"initializeJavaContextClassLoader");
initializeJavaContextClassLoader();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
// 通過類加載器創(chuàng)建Application對象
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
if (!mActivityThread.mInstrumentation.onException(app, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Unable to instantiate application " + appClass
+ ": " + e.toString(), e);
}
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {
try {
// 調(diào)用Application的onCreate方法
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}
...
return app;
}
- 創(chuàng)建ContextImpl對象,并通過Activity的attach方法來完成一些重要數(shù)據(jù)的初始化
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
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, window);
ContextImpl
是一個(gè)很重要的數(shù)據(jù)結(jié)構(gòu),很明顯是Context
的具體實(shí)現(xiàn),Context
中大部分邏輯都是由ContextImpl
實(shí)現(xiàn)的。ContextImpl
通過Activity的attach
方法來和Activity建立關(guān)聯(lián),同時(shí)在attach
方法中還會(huì)完成Window
的創(chuàng)建并建立自己和Window
的關(guān)聯(lián),Window
接收到外部事件輸入后將事件傳遞給Activity。
- 調(diào)用Activity的onCreate方法
mInstrumentation.callActivityOnCreate(activity, r.state);
上述代碼中調(diào)用Activity的onCreate
方法,意味著Activity已經(jīng)完成了整個(gè)啟動(dòng)過程。此外還調(diào)用了Activity的onStart
,OnRestoreInstanceState
方法:
activity.performStart();
...
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
總結(jié)
至此,整個(gè)Activity的啟動(dòng)流程已經(jīng)分析完了,其中還有很多細(xì)節(jié)需要打磨:
- 啟動(dòng)過程中涉及到的類的作用分別是什么,我們并沒有深入分析
- 可以看出,Activity啟動(dòng)最后涉及到Handler消息循環(huán)機(jī)制,可以參考我的上一篇文章:Android消息機(jī)制Handler
- Activity啟動(dòng)過程中AMS的地位顯著,但是進(jìn)程間通信的具體本質(zhì)我也沒有分析,下一步可以分析下Android IPC機(jī)制
- Android從開機(jī)到點(diǎn)擊Icon打開APP的過程中涉及到Launcher(它其實(shí)也是一個(gè)android應(yīng)用程序)的啟動(dòng)以及APP進(jìn)程的創(chuàng)建,我們此處沒有提及,以后的博客中我也會(huì)整理分析
參考信息
- 任玉剛.《Android開發(fā)藝術(shù)探索》
- Android Launcher 啟動(dòng) Activity 的工作過程