概括
先簡略概括一下Activity的啓動過程,以下拿點擊Launcher來說。
1.開始請求執行Activity,Launcher進程發送命令到AMS
Launcher就是一個App,點擊Launcher會隱式啓動一個新的應用。所以跑的也是Activity.startActivity的流程。
接着就是Activity.startActivityForResult() ——> Instrumentation.execStartActivity()...一系列方法。
2.AMS執行Launcher(棧頂Activity)的onPause方法
AMS通過Binder執行Launcher的onPause方法
3.啓動Activity所屬的應用進程
-從Zygote中fork一個新應用進程出來。裏面有負責調度ActivityRecord和Task的代碼。
調度Task的算法涉及的判斷很多,和當前回退棧,要啓動的activity的啓動模式,以及taskAffinity屬性,啓動Activity時設置的intent的flag等諸多要素相關
-之後會執行ActivityThread類的main方法。Activity就在這個ActivityThread實例中運行。
4.執行啓動Activity
AMS通過代理,請求啓動Activity。ApplicationThread通知主線程執行該請求。然後,ActivityThread執行Activity的啓動,並執行它的生命週期方法。
在ApplicationThreaad中,對應AMS管理Activity生命週期的方法都以scheduleXXXActivity,ApplicationThread在Binder線程中,它會向主線程發送消息,ActivityThread的Handler會調用相應的handleXXXActivity方法,然後會執行performXXXActivity方法,最終調用Activity的onXXX方法。
5.AMS執行Launcher(棧頂Activity)的onStop方法
AMS通過Binder執行Launcher的onStop方法
--------------------------分割線--------------------------
前置說明:安卓衆多應用來回切換,肯定不是兩兩應用進行通信能協調好的事,所以需要一個總管家的身份。這裏就是我們的AMS。它掌管着所有Activity的生命週期。
已知AMS是運行在SystemServer這個進程上,衆多Activity運行在各種應用進程中,那麼問題來了...
重點一:衆多Activity怎麼與AMS通信的
先來兩張UML圖
一個圖是關於ActivityManager,一個是關於ApplicationThread。
拿ActivityManager這個UML圖來分析一下。ApplicationThread跟這個差不多。
我們知道用android實現IPC,寫個XXX.aidl,ide會爲我們生成一個同文件名不同後綴的XXX.java文件。這個文件裏面的結構就像這張UML圖的結構。
1.這個XXX.java類首先是一個接口,繼承IInterface接口。裏面一般聲明瞭需要提供的業務方法。在這裏就是IActivityManager。
2.然後XXX.java有一個內部有個抽象類Stub繼承Binder實現XXX接口。在這裏就是ActivityManagerNative+ActivityManagerProxy。
3.Stub裏面還有內部類Proxy實現了XXX接口。在這裏就是ActivityManagerProxy。
ActivityManagerNative即Stub相當於服務端。ActivityManagerProxy即Proxy相當於客戶端。所以ActivityManager設計成這樣的aidl結構完成通信。
再具體一點,來看看這個機制怎麼完成startActivity方法。
首先是從Activity.startActivity --> Activity.startActivityForResult() --> Instrumentation.execStartActivity()
然後就會調用ActivityManagerNative.getDefault().startActivity()方法
getDefault會嘗試通過ServiceManager.getService("activity")遠程服務的Binder對象,然後進行asInterface轉換成IActivityManager,其實返回的就是ActivityManagerProxy。
源碼是這個樣子的。
先看getDefault部分,使用了自帶的Singleton類實現單例模式,並且聲明是靜態方法。
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 getDefault() {
return gDefault.get();
}
然後看startActivity部分,類ActivityManagerProxy的startActivity方法
class ActivityManagerProxy implements IActivityManager {
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
if (options != null) {
data.writeInt(1);
options.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
}
裏面是對參數使用Parcel序列化,然後調用transact方法,參數是方法名標識,參數,盛放返回值的容器。
這樣就會跳轉到ActivityManagerService的onTransact方法,ActivityManagerService會調用父類ActivityManagerNative的onTransact方法。
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case START_ACTIVITY_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
String callingPackage = data.readString();
Intent intent = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
IBinder resultTo = data.readStrongBinder();
String resultWho = data.readString();
int requestCode = data.readInt();
int startFlags = data.readInt();
ProfilerInfo profilerInfo = data.readInt() != 0
? ProfilerInfo.CREATOR.createFromParcel(data) : null;
Bundle options = data.readInt() != 0
? Bundle.CREATOR.createFromParcel(data) : null;
int result = startActivity(app, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
reply.writeNoException();
reply.writeInt(result);
return true;
}
}
}
所以客戶端調用的方法都要經過onTransact方法轉化。所以裏面switch判斷一下標識,就進入START_ACTIVITY_TRANSACTION的case裏面。裏面也有一個startActivity方法(注意此時已經位於AMS進程中了),在ActivityManagerNative這個抽象類裏沒有實現這個方法,所以交給AMS具體實現的方法來處理了。
所以ActivityManagerNative主要是負責Binder機制中,接受參數,轉換處理參數這些功能。之後把參數整理好,纔會交個AMS,AMS纔是具體的處理業務的邏輯。
之後就是AMS的startActivity方法了,這裏面的調用鏈和處理邏輯就多了。
比如判斷這個新進程是不是已經啓動了,不需要再從zygote中fork一個進程出來。。。。。。。。。
ps:所以在我腦裏,我覺得這兩張UML圖附上一點業務邏輯,應該是這樣。紅色部分的是業務邏輯
重點二:ActivityThread的Main方法幹了什麼
從zygote中fork出一個新進程後,就會執行ActivityThread的main方法。
經典問題,一個App的程序入口到底是什麼?回答的就是這個ActivityThread的main方法了
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
AndroidKeyStoreProvider.install();
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
1.這裏有關於主線程Looper的操作
我們知道如果主線程像子線程發送消息,需要有Looper.prepare()和Looper.loop()操作。
在這裏就是prepareMainLooper(),因爲這是主線程,這名字簡直不能更形象了。
2.這裏有new ActivityThread()。
3.thread.attach(false); 執行ActivityThread的attach方法。看下源碼,挑出重點
private void attach(boolean system) {
...
if (!system) {
...
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
}
...
}
裏面依舊ActivityManagerNative.getDefault()獲取到ActivityManagerProxy。執行attachApplication方法,傳的參數mAppThread類型是ApplicationThread。
這個mAppThread是在new ActivityThread()時做爲成員變量同時初始化的。
然後中間過程同上面之前說的ActivityManager的binder機制調用流程,這裏忽略這些流程,直接看AMS的attachApplication方法。
AMS的attachApplication方法調用attachApplicationLocked方法,裏面參數就是當初傳過去的ApplicationThread。
接着在這裏面又用了這個ApplicationThread調用了bindApplication方法。
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableOpenGlTrace, boolean trackAllocation, boolean isRestrictedBackupMode,
boolean persistent, Configuration config, CompatibilityInfo compatInfo,
Map<String, IBinder> services, Bundle coreSettings) {
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableOpenGlTrace = enableOpenGlTrace;
data.trackAllocation = trackAllocation;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
sendMessage(H.BIND_APPLICATION, data);
}
最後一行看到發消息了,其實發到mH這個Handler裏面。
點進去handleMessage方法,能看到很多case,比如LAUNCH_ACTIVITY, PAUSE_ACTIVITY, RESUME_ACTIVITY, DESTROY_ACTIVITY這種跟Activity相關的
還有CREATE_SERVICE, BIND_SERVICE, UNBIND_SERVICE, STOP_SERVICE跟Service相關的。
大概能猜出,這是AMS管理App的一道關卡。
我們找到BIND_APPLICATION標識,看到他進入了handleBindApplication方法裏面。
private void handleBindApplication(AppBindData data) {
...
if (data.instrumentationName != null) {
...
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
...
} else {
mInstrumentation = new Instrumentation();
}
...
try {
...
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
...
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}
...
}
裏面有新建Instrumentation的代碼,能理解,Activity的生命週期方法都是Instrumentation調用的,當然要先new一個。
然後是makeApplication這個方法,這名字+返回值是個Application,很容易猜到是創建應用的Application。進去裏面一看,果然是這樣。
這個創建方法需要在LoadedApk中轉一手,需要需要這個類是可以讀取到xml裏面的自定義Application的類名字符串(入股有自定義Application的話,沒有會用默認字符串“android.app.Application”)。
然後根據類的全名用反射newInstance出來一個Application。
最後調用callApplicationOnCreate,裏面只有一個代碼,就是執行application的onCreate方法。
所以其中一個重要流程是,運行應用Application的相關業務。接下來回到ActivityManagerService的attachApplicationLocked方法中,下一步是mStackSupervisor.attachApplicationLocked(app)。
這個app是ProcessRecord的類型,本來我覺得這是AMS(服務端)保存某一個應用(客戶端)信息的實體,心裏稱它爲“應用實體信息類”。後來發現並不能這樣想,因爲一個進程裏面可能有多個應用的Activity,所以還是隻能稱爲“進程實體信息類”。
attachApplicationLocked方法裏面會調用realStartActivityLocked方法,裏面有一句代碼app.thread.scheduleLaunchActivity。這個thread是實際上是ApplicationThreadProxy類的實體,所以這句話會通過binder機制,調用到ApplicationThread裏面的scheduleLaunchActivity方法。
在這個方法的後一行看到發送一個LAUNCH_ACTIVITY的消息到H這個Hander裏面。找到LAUNCH_ACTIVITY這個case,我們看到執行了handleLaunchActivity方法。
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Activity a = performLaunchActivity(r, customIntent);
...
if (a != null) {
...
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
...
}
裏面有兩行重要的代碼,重要代碼一,執行perforLaunchActivity方法。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
...
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
...
return activity;
}
裏面有一句mInstrumentation.newActivity方法。點進去只有一句代碼,功能就是通過反射創建出一個Activity實體。
然後下面會有mInstrumentation.callActivityOnCreate方法。裏面的調用鏈是Activity.performCreate()——>Activity.onCreate()這樣就執行了我們熟悉的onCreate方法。
後面又有activity.performStart()。裏面的調用鏈是Instrumentation.callActivityOnStart()——>Activity.onStart()。
然後回到handleLaunchActivity的重要代碼二,handleResumeActivity裏面的調用鏈是ActivityThread.performResumeActivity()——>Activity.performResume()——>Instrumentation.callActivityOnResume()——>Activity.onResume().執行了我們熟悉的onResume方法。這樣Activity啓動的主要流程就跑完了。
總結一下重點二。
首先想講一下之前一直沒搞清ApplicationThread和ActivityThread這兩者的區別。這兩個名字實在給我造成了很大的誤會。
看了源碼後,才知道。ActivityThread本質是一個線程,最關鍵的是它竟然沒繼承Thread我也是很納悶!!我們常說的UI線程,主線程就是這貨。
ApplicationThread跟Thread沒多大關係,它主要是配合ApplicationThreadNative和ApplicationThreadProxy完成Binder進程間通信的。所以爲啥元老Android發明者一開始要給定這個名字呢??
然後想講其實整個ActivityThread的attach方法,裏面涉及的代碼,所有方法調用鏈,隨便拿出一個來我感覺細聊的話都可以寫篇文章。
很多細節比如intent的傳遞,ActivityThread時候時候會新建進程什麼時候會尋找已有進程,activity啓動是在具體什麼時候讀取的xml裏面該activity標籤的自定義屬性的等等,都暫時忽略了。
//TODO
//給上面代碼調用畫個時序圖。。。