Activity 源碼解析
Activity是Android里非常重要的一個組件。東西非常多,如果本文有沒有覆蓋到要糊,但你又覺得非常重要的部分,歡迎給我反饋妆丘。如果你發(fā)現(xiàn)了任何錯誤也歡迎給我反饋锄俄。(Email:zhxilong2015@gmail.com)
以下全部基于Android 8.0 Api26的源碼分析。不同版本可能稍有不同勺拣。但整個基本原理其實(shí)是完全一樣的奶赠。
既然是源碼分析,所以這里不會去做功能分析宣脉,比如Activity都有什么功能车柠,startActivity怎么調(diào)用剔氏,怎么給Activity添加專場動畫等塑猖,這里會著重分析Activity從創(chuàng)建到結(jié)束,都經(jīng)過了哪些過程谈跛,這些過程代碼都在什么位置羊苟,Activity是在哪里new出來的,生命周期為什么能被回調(diào)等等這些感憾,本文會跟隨著Android系統(tǒng)的代碼執(zhí)行順序蜡励,一步步從Activity被創(chuàng)建分析到Activity被銷毀。大致會從以下幾個部分來介紹,有一定的閱讀門檻:
- Android消息機(jī)制
- ActivityThread介紹
- Activity如何收到消息
- Activity的生命周期事件
- Activity結(jié)束
- 總結(jié)
1. 簡介
Activity是Android的四大組件之一凉倚,光注釋都五六百行兼都。大致從注釋能看到Activity本身是為UI服務(wù)的,介紹了生命周期和一些常用功能稽寒。更詳細(xì)的還需要從源碼層面分析扮碧。
2. 源碼分析
1.Android消息機(jī)制
除了類似單片機(jī)這種特殊的操作系統(tǒng),大部分操作系統(tǒng)都會有消息機(jī)制杏糙。消息機(jī)制把軟件需要執(zhí)行的代碼都包裝成消息慎王。有了消息機(jī)制可以很方便的讓軟件對外界操作進(jìn)行實(shí)時響應(yīng)。一個RecyclerView宏侍,你上滑一下赖淤,RecyclerView滑動還沒有結(jié)束你這時候可以按住RecyclerView,RecyclerView會實(shí)時響應(yīng)你的操作讓滑動立刻停止谅河。怎么做到的咱旱?其實(shí)就是消息機(jī)制。RecyclerView的滑動被分割成了若干個消息绷耍,每個消息都移動一小段距離莽龟,這時候你突然按住RecyclerView,你的操作會被立即插入到消息循環(huán)锨天,這時候不再執(zhí)行移動的操作毯盈,而是響應(yīng)你按住這個操作,讓RecyclerView立刻停止病袄。用戶看到的效果就是App實(shí)時響應(yīng)了用戶的請求搂赋,沒有因?yàn)锳pp當(dāng)前正在滑動RecyclerView而用戶等待動畫結(jié)束。
在Android中實(shí)現(xiàn)消息機(jī)制的就是Handler益缠、Message脑奠、MessageQueue、Looper這四兄弟幅慌。任何操作都被封裝成Message被添加到MessageQueue中宋欺,Looper負(fù)責(zé)消息的循環(huán),拿到消息后交給Handler來處理胰伍。
這里之所以要簡單介紹消息機(jī)制齿诞,主要就是Activity的各種事件本質(zhì)來源其實(shí)都是Handler消息。知道消息機(jī)制骂租,接下來就會很容易理解Activity的一系列事件回調(diào)祷杈。
2.ActivityThread介紹
Java可以很方便的隨時Dump當(dāng)前的方法棧,可以看到當(dāng)前代碼是經(jīng)過了怎樣的方法棧被調(diào)到的渗饮。
at android.app.Activity.performCreate(Activity.java:6975)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2784)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2906)
at android.app.ActivityThread.-wrap11(ActivityThread.java:-1)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1605)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:172)
at android.app.ActivityThread.main(ActivityThread.java:6637)
at java.lang.reflect.Method.invoke(Method.java:-1)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
在任意一個Activity的onCreate加個斷點(diǎn)但汞,可以得到以上方法棧數(shù)據(jù)宿刮。或者每當(dāng)App崩潰的時候也會有類似數(shù)據(jù)被輸出到Log私蕾,再或者也可以通過
Thread.currentThread().getStackTrace();
得到方法棧自己輸出到Logcat僵缺。除了關(guān)注自己代碼部分,可能很少會有人去關(guān)注下面這些方法踩叭。下面這些方法你有看到Looper.loop嗎谤饭?這不是我們的消息循環(huán)嗎?loop是被誰調(diào)用的懊纳?ActivityThread.main揉抵。ActivityThread的main方法就是Android App的入口代碼(這個入口是被ActivityManagerService定義的,那可以在ActivityManagerService中找到相關(guān)代碼嗤疯,這里不做詳細(xì)介紹)冤今。ActivityThread源碼包含在SDK中(如果你雙擊Shift輸入ActivityThread IDE沒有找到這個類的話,你可以先找到Activity類茂缚,然后在Activity源碼中find查找ActivityThread戏罢,然后通過快捷鍵跟進(jìn)ActivityThread源碼)。
定位到main方法:
public class ActivityThread{
...
private void attach(boolean system) {
if (!system) {
...
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
...
}
}
...
public static void main(String[] args) {
......
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
}
基本上做了兩件事脚囊,初始化ActivityThread(注意有個mgr.attachApplication(mAppThread)注冊mAppThread)龟糕,然后在main方法最后進(jìn)入了Looper.loop的消息循環(huán),因?yàn)檫@個循環(huán)是不會結(jié)束的悔耘,所以最后一個異常正常情況下是不會被執(zhí)行到的讲岁。當(dāng)然你可以通過
Looper.getMainLooper().quit();
強(qiáng)行讓主線程消息循環(huán)結(jié)束。
看到這里我們應(yīng)該明白衬以,在App初始化完成后缓艳,執(zhí)行的代碼都會進(jìn)入到Looper中執(zhí)行,所以就很容易理解看峻,其實(shí)我們的Activity創(chuàng)建阶淘,Activity生命周期回調(diào)也將是Handler消息的形式。
在ActivityThread類中有個內(nèi)部類H互妓,繼承自Handler溪窒。H類定義了很多類型的int,看名字其實(shí)很容易跟生命周期回調(diào)對應(yīng)起來冯勉。
3.Activity如何收到消息
前面我們知道Looper.loop之后澈蚌,App要想執(zhí)行代碼,肯定是通過HandlerMessage的形式珠闰。那么Activity在創(chuàng)建前一定是收到了一個HandlerMessage惜浅。找到處理Message的H類,里面有個LAUNCH_ACTIVITY伏嗜。
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
...
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
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;
...
}
...
}
}
在handleMessage時候通過handleLaunchActivity來處理LAUNCH_ACTIVITY消息坛悉。
在分析處理部分的代碼前,我們回過來想下LAUNCH_ACTIVITY消息是被誰發(fā)出的呢承绸?find搜下裸影。
class ActivityThread{
...
private class ApplicationThread extends IApplicationThread.Stub {
...
@Override
public final void scheduleLaunchActivity(...){
...
sendMessage(H.LAUNCH_ACTIVITY, r);
}
...
}
...
}
保留關(guān)鍵代碼就是上面的結(jié)構(gòu)。到這里創(chuàng)建Activity的代碼军熏,其實(shí)都涉及到了轩猩。為了更清楚的理解,我們再把代碼順序梳理下荡澎,就是下面的代碼從上到下均践。我用“>數(shù)字”標(biāo)出了代碼執(zhí)行順序。順著數(shù)字順序可以很清晰的理解這個過程摩幔。
public class ActivityThread{
...
// >1
// App入口
public static void main(String[] args) {
......
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
// >2
// 初始化一些必要數(shù)據(jù)
thread.attach(false);
// >5
// 啟動消息循環(huán)
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
...
// >3
private void attach(boolean system) {
if (!system) {
...
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManager.getService();
try {
// >4
// 注冊binder到遠(yuǎn)端ActivityManagerService
// 注冊完成后mAppThread就可以接收ActivityMangerService跨進(jìn)程發(fā)過來的消息了彤委。
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
...
}
}
...
private class ApplicationThread extends IApplicationThread.Stub {
...
// >6
// 遠(yuǎn)端ActivityManagerService通過Binder跨進(jìn)程通信,
// 調(diào)到這個方法或衡,當(dāng)前在App的Binder線程焦影。
@Override
public final void scheduleLaunchActivity(...){
...
// >7
// 由于此時在Binder線程,所以不能直接調(diào)用handleLaunchActivity方法封断。
// 需要通過Handler跨線程通信給主線程發(fā)LAUNCH_ACTIVITY消息斯辰。
sendMessage(H.LAUNCH_ACTIVITY, r);
}
...
}
...
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
...
// >8
// 主線程收到LAUNCH_ACTIVITY消息。
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
// 處理LAUNCH_ACTIVITY消息
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
// >9
// 打開Activity
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
}
...
}
...
}
}
LAUNCH_ACTIVITY事件從scheduleLaunchActivity發(fā)出坡疼。那scheduleLaunchActivity被誰調(diào)用彬呻?還記得前面初始化ActivityThread我說的(注意有個setApplicationObject注冊mAppThread)嗎?ApplicationThread繼承自IApplicationThread.Stub柄瑰,看到Stub是不是覺得很熟悉废岂?就是Binder跨進(jìn)程通信。
在Looper進(jìn)入loop循環(huán)前狱意,調(diào)用了ActivityThread.attach方法湖苞,在attach中將ApplicationThread綁定到了系統(tǒng)的ActivityManagerService進(jìn)程。此時只要ActivityManagerSercice通過跨進(jìn)程通信給App發(fā)LAUNCH_ACTIVITY消息详囤,那么ApplicationThread的scheduleLaunchActivity將收到LAUNCH_ACTIVITY消息财骨,但是因?yàn)榇藭rApplicationThread是在Binder線程,所以此時將通過Handler跨線程給主線程發(fā)LAUNCH_ACTIVITY藏姐,主線程的H類的handlerMessage收到LAUNCH_ACTIVITY隆箩,然后調(diào)用handleLaunchActivity(這里梳理了下系統(tǒng)是如何收到打開Activity消息的,后面還會把怎么發(fā)出消息即startActivity也給分析下)羔杨。
3.Activity的生命周期事件
把App如何接收LAUNCH_ACTIVITY消息梳理完了捌臊,下面就要開始Activity是怎么被new的,以及Activity是如何收到各種聲明周期事件的兜材。還是老樣子理澎,我把Activity創(chuàng)建和生命周期相關(guān)關(guān)鍵代碼貼出來逞力,并用“>數(shù)字”來標(biāo)注執(zhí)行順序。
// >1
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
...
// Initialize before creating the activity
WindowManagerGlobal.initialize();
// 創(chuàng)建Activity以及處理生命周期
// >2
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
...
// >12
// onResume
handleResumeActivity(...);
...
}
} else {
...
}
}
// >3
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
// >4
// 創(chuàng)建Activity實(shí)例
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
...
} catch (Exception e) {
...
}
try {
...
activity.attach(...);
...
// >7
// onCreate
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
// >8
// onStart
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
// >9
// onRestore
if (!r.activity.mFinished) {
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
// >10
// onPostCreate
if (!r.activity.mFinished) {
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPostCreate()");
}
}
r.paused = true;
// >11
// 持有Activity實(shí)例的r被添加到mActivities中糠爬。
mActivities.put(r.token, r);
...
} catch (Exception e) {
...
}
...
}
// >13
final void handleResumeActivity(...) {
...
// >14
// onResume
r = performResumeActivity(token, clearHide, reason);
if (r != null) {
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
// 不可見寇荧,后面會通過activity.makeVisible()恢復(fù)可見
decor.setVisibility(View.INVISIBLE);
...
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
// >17
// 被添加到WindowManager
wm.addView(decor, l);
} else {
...
}
}
...
// 恢復(fù)Activity可見
r.activity.makeVisible();
...
...
}
}
}
...
// >15
// onResume
public final ActivityClientRecord performResumeActivity(...) {
...
if (r != null && !r.activity.mFinished) {
...
try {
...
// >16
// onResume
r.activity.performResume();
...
} catch (Exception e) {
...
}
}
public class Instrumentation {
...
// >5
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
// >6
// 通過反射創(chuàng)建Activity實(shí)例
return (Activity)cl.loadClass(className).newInstance();
}
...
}
我已經(jīng)用“>數(shù)字”把主要的事件執(zhí)行順序回調(diào)貼出來了。按照順序可以很清晰的看到一個Activity是怎么被創(chuàng)建出來的执隧,以及創(chuàng)建出來后比如onCreate揩抡、onStart等各個生命周期是如何收到回調(diào)事件的。收到LAUNCH_ACTIVITY消息后镀琉,ActivityManagerService不需要再發(fā)送RESUME_ACTIVITY消息峦嗤,LAUNCH_ACTIVITY處理過程會直接處理掉onStart,onResume屋摔。
那假如我此時按下Home鍵后烁设,App要收到onPause消息,我們來分析下這個過程凡壤。
按下Home后署尤,ActivityManagerService將通過跨進(jìn)程通信給App發(fā)送PAUSE_ACTIVITY的消息。
public final class ActivityThread {
private class ApplicationThread extends IApplicationThread.Stub {
...
// >1
// 當(dāng)前在Binder線程收到ActivityManagerService跨進(jìn)程通信
public final void schedulePauseActivity(...) {
...
// >2
// 此時在Binder亚侠,給主線程發(fā)PAUSE_ACTIVITY的消息
// 如果是finished就發(fā)送PAUSE_ACTIVITY_FINISHING消息曹体。
sendMessage(
finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
token,
(userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
configChanges,
seq);
}
...
}
private class H extends Handler {
// >3
// 此時進(jìn)入主線程
public void handleMessage(Message msg) {
switch (msg.what) {
case PAUSE_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
SomeArgs args = (SomeArgs) msg.obj;
// >4
// onPause∏
handlePauseActivity((IBinder) args.arg1, false,
(args.argi1 & USER_LEAVING) != 0, args.argi2,
(args.argi1 & DONT_REPORT) != 0, args.argi3);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
}
}
}
// >5
private void handlePauseActivity(...) {
...
if (r != null) {
//Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
if (userLeaving) {
// >6
// 見過這個生命周期嗎?
performUserLeavingActivity(r);
}
// >8
performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
...
}
}
// >7
final void performUserLeavingActivity(ActivityClientRecord r) {
mInstrumentation.callActivityOnUserLeaving(r.activity);
}
// >9
final Bundle performPauseActivity(IBinder token, boolean finished,
boolean saveState, String reason) {
ActivityClientRecord r = mActivities.get(token);
// >10
// 重載performPauseActivity
return r != null ? performPauseActivity(r, finished, saveState, reason) : null;
}
// >11
final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
boolean saveState, String reason) {
...
// >12
// 回調(diào)onSaveInstanceState
// Next have the activity save its current state and managed dialogs...
if (!r.activity.mFinished && saveState) {
callCallActivityOnSaveInstanceState(r);
}
// >13
performPauseActivityIfNeeded(r, reason);
...
// >16
return !r.activity.mFinished && saveState ? r.state : null;
}
// >14
private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
...
try {
...
// >15
// 回調(diào)onPause
mInstrumentation.callActivityOnPause(r.activity);
...
} catch (...) {
...
}
r.paused = true;
}
}
好了硝烂,onPause結(jié)束箕别。過程很簡單,順便還能學(xué)到一個回調(diào)performUserLeavingActivity滞谢。同樣的onResume過程跟onPause過程基本差不多串稀,這里就不再啰嗦了。
到了這里其實(shí)你應(yīng)該也就非常清楚了所有生命周期回調(diào)的先后順序狮杨,以及每個生命周期具體是怎么回調(diào)到Activity的母截。那么生命周期的介紹就算告一個段落了。
4.Activity的結(jié)束
這里再說下mActivies橄教。
public final class ActivityThread {
...
// 在低版本上這里是用的HashMap
final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
...
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
mActivities.put(r.token, r);
...
}
...
}
還記得前面在LaunchActivity的時候把持有Activity實(shí)例的ActivityClientRecord r被put到mActivities嗎清寇?Java不需要自己手動處理對象釋放,Java會通過自己的GC來釋放护蝶。那么Activity對象在創(chuàng)建后肯定需要一個對象來持有它华烟,否則Activity實(shí)例在GC時候就會被銷毀了。那么誰來持有Activity持灰?就是這里到mActivities盔夜。所有Activity被創(chuàng)建后都會被添加進(jìn)來,當(dāng)然與之對應(yīng)的就會在onDestory的時候從mActivities中移除。你可以嘗試用上面分析的過程去找下什么時候被移除的喂链。
3. 總結(jié)
Activity的東西非常多返十,但只要理解了其中的規(guī)律,就會很容易舉一反三衩藤。如果你看明白了這整個過程吧慢,就可以很輕松的通過H類定義的msg.what涛漂,找到App都能接受到多少種不同類型的系統(tǒng)回調(diào)赏表。這些回調(diào)有Activity的,也有Service的匈仗,也有Application的等等瓢剿。同樣的方法你可以很容易分析Service的消息處理過程,大家都在說Service onStartCommand是發(fā)生在主線程悠轩,那么為什么是主線程间狂?同樣的思路,你可以非常容易弄明白這個過程火架。