Android那兩個你碰不到但是很重要的類之ActivityThread
前言
上篇文章我們聊了些Android里那些我們平時碰不到但很重要的類ViewRootImpl,這一篇我們就來看看另外那個類ActivityThread。
通過本文能了解一下內(nèi)容

1、和系統(tǒng)進程打交道的橋頭堡
應用進程起來之后ART(Android Runtime)第一站就是ActivityThread,代碼層面上就是ActivityThread的main()方法,是不是很熟悉,爺青回啊,這不就是java的main方法嘛
public static void main(String[] args) {
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
sMainThreadHandler = thread.getHandler();
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}該方法是一個靜態(tài)方法,里面做了重要的兩件事
- 創(chuàng)建了讓主線程Looper開始工作,并創(chuàng)建了一個Handler
- 給system_server【遞紙條】告訴他聯(lián)系方式,告訴sytem_servr進程與應用進程取得聯(lián)系可以通過ApplicationThread這個binder。看下面這個代碼
private void attach(boolean system, long startSeq) {
final IActivityManager mgr = ActivityManager.getService();
mgr.attachApplication(mAppThread, startSeq);//調(diào)用遠端的binder
}- 通過
ActivityManager.getService()拿到system_server進程的binder,然后把mAppThreadbinder傳遞過去。mAppThread是ApplicationThread的一個對象,是ActivityThread的一個內(nèi)部類。 - 取得聯(lián)系后的第一站創(chuàng)建Applicaiton。
private class ApplicationThread extends IApplicationThread.Stub {
@Override
public final void bindApplication() {
sendMessage(H.BIND_APPLICATION, data);
}- 接下來就是H主線程的Hanlder,調(diào)用handleBindApplication
private void handleBindApplication(AppBindData data) {
Application app;
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo, isSdkSandbox);//內(nèi)部創(chuàng)建LoadedApk
app = data.info.makeApplicationInner(data.restrictedBackupMode, null);//內(nèi)部創(chuàng)建Applicaiton對象,調(diào)用onCreate()方法
installContentProviders(app, data.providers); //cotentprovider初始化
mInstrumentation.callApplicationOnCreate(app);//調(diào)用onCreate()方法
}- 這里找到了為什么使用ContentProvider能夠?qū)崿F(xiàn)初始化,構建的時候會創(chuàng)建ContenProvider。

- IActivityManager(binder):應用進程和SystemServer進程打交道的時候。
- AppliactionThread(binder):SystemServer進程與應用進程通信。
2、為什么使用ContentProvider可以實現(xiàn)初始化
private void handleBindApplication(AppBindData data) {
Application app;
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo, isSdkSandbox);//內(nèi)部創(chuàng)建LoadedApk
app = data.info.makeApplicationInner(data.restrictedBackupMode, null);//內(nèi)部創(chuàng)建Applicaiton對象,調(diào)用onCreate()方法
installContentProviders(app, data.providers); //cotentprovider初始化
mInstrumentation.callApplicationOnCreate(app);//調(diào)用onCreate()方法
}上一段分析時已經(jīng)找打了答案,應用進程被拉起來之后,在創(chuàng)建Application對象調(diào)用attachBaseContext()和onCreate()方法之間會調(diào)用ContentProvider的onCreate()方法這也是很多第三方SDK使用該特性實現(xiàn)初始化的原理。
3、Activity是什么時候開始渲染的
public void handleResumeActivity() {
performResumeActivity(r, finalStateRequest, reason)//調(diào)用Activity onResume
final Activity a = r.activity;
View decor = r.window.getDecorView();
ViewManager wm = a.getWindowManager();
a.mWindowAdded = true;
wm.addView(decor, l);
}ActivityThread.java的handleResumeActivity()有這樣一段代碼,我們可以得出結論,Activity渲染的起點是在 onResume階段,在onResume階段會把decorView交給WindowManager開始執(zhí)行渲染。
4、原來還可以監(jiān)控組件的生命周期
class H extends Handler {
public static final int RECEIVER = 113; //廣播接收者
@UnsupportedAppUsage
public static final int CREATE_SERVICE = 114;//Service創(chuàng)建
public static final int INSTALL_PROVIDER = 145;//ContentProvider
public static final int RELAUNCH_ACTIVITY = 160; //Activity啟動
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case RECEIVER:
handleReceiver((ReceiverData)msg.obj);
break;
case CREATE_SERVICE:
handleCreateService((CreateServiceData)msg.obj);
break;
case BIND_SERVICE:
handleBindService((BindServiceData)msg.obj);
break;
case RELAUNCH_ACTIVITY:
handleRelaunchActivityLocally((IBinder) msg.obj);
break;
}
}
}系統(tǒng)進程(system_server)指揮應用進程組件生命周期的第一站其實就在ActivityThread這里,交給H對象其實是主線程的Handler來分發(fā)處理,如上。我們可以反射拿到這一信息,可以監(jiān)控到主線程對于這些組件調(diào)度的信息,這一信息對我們監(jiān)控排查ANR很有幫助。
5 、SharedPreference被聲討的根源
private void handleStopService(IBinder token) {
QueuedWork.waitToFinish();
}
public void handlePauseActivity(){
QueuedWork.waitToFinish();
}
public void handleStopActivity(){
QueuedWork.waitToFinish();
}
public void handleServiceArgs(){
QueuedWork.waitToFinish();
}ActivityThread的以上方法里會調(diào)用 QueuedWork.waitToFinish(); 該代碼會堵塞主線程執(zhí)行等待SP的寫入操作。這也是SP造成ANR的根源。
稍微展開點
public static void waitToFinish() {
while (true) {
Runnable finisher;
synchronized (sLock) {
finisher = sFinishers.poll();
}
if (finisher == null) {
break;
}
finisher.run();
}
}
}waitToFinish()方法里有這樣一段代碼,sFinishers是一個List里面是存放的SP寫入操作,會在SP執(zhí)行commit和apply的時候放入進來。字節(jié)跳動團隊就是在此處hook了使其poll()方法永遠放回空,來杜絕此處產(chǎn)生的ANR。
7 、總結
通過閱讀ActivityThread的源碼我們能在其中獲取很多有用的知識。系統(tǒng)進程和應用進程通信的橋梁,Activity真正渲染的起始點,ContentProvider能實現(xiàn)SDK自動初始化的原理等都在ActivityThread看到他們的影子,希望本文對你有所啟發(fā)有所幫助。
以上就是Android那兩個你碰不到但是很重要的類之ActivityThread的詳細內(nèi)容,更多關于Android ActivityThread的資料請關注腳本之家其它相關文章!
相關文章
Android NDK開發(fā)的環(huán)境搭建與簡單示例
本文主要介紹Android NDK的知識,這里整理了相關資料,來說明如何搭建相應環(huán)境和簡單實例,幫助大家理解,有興趣的小伙伴可以參考下2016-09-09
Android 實現(xiàn)無網(wǎng)絡頁面切換的示例代碼
本篇文章主要介紹了Android 實現(xiàn)無網(wǎng)絡頁面切換的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09
Flutter路由跳轉(zhuǎn)參數(shù)處理技巧詳解
這篇文章主要為大家介紹了Flutter路由跳轉(zhuǎn)參數(shù)處理技巧示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-08-08
Android實現(xiàn)動態(tài)自動匹配輸入內(nèi)容功能
這篇文章主要為大家詳細介紹了Android實現(xiàn)動態(tài)自動匹配輸入內(nèi)容功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06
Android實現(xiàn)Neumorphism?UI控件
大家好,本篇文章主要講的是Android實現(xiàn)Neumorphism?UI控件,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下2022-02-02

