Android那兩個(gè)你碰不到但是很重要的類之ActivityThread
前言
上篇文章我們聊了些Android
里那些我們平時(shí)碰不到但很重要的類ViewRootImpl
,這一篇我們就來看看另外那個(gè)類ActivityThread。
通過本文能了解一下內(nèi)容
1、和系統(tǒng)進(jìn)程打交道的橋頭堡
應(yīng)用進(jìn)程起來之后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"); }
該方法是一個(gè)靜態(tài)方法,里面做了重要的兩件事
- 創(chuàng)建了讓主線程Looper開始工作,并創(chuàng)建了一個(gè)Handler
- 給system_server【遞紙條】告訴他聯(lián)系方式,告訴sytem_servr進(jìn)程與應(yīng)用進(jìn)程取得聯(lián)系可以通過ApplicationThread這個(gè)binder??聪旅孢@個(gè)代碼
private void attach(boolean system, long startSeq) { final IActivityManager mgr = ActivityManager.getService(); mgr.attachApplication(mAppThread, startSeq);//調(diào)用遠(yuǎn)端的binder }
- 通過
ActivityManager.getService()
拿到system_server
進(jìn)程的binder,然后把mAppThread
binder傳遞過去。mAppThread
是ApplicationThread
的一個(gè)對(duì)象,是ActivityThread的一個(gè)內(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對(duì)象,調(diào)用onCreate()方法 installContentProviders(app, data.providers); //cotentprovider初始化 mInstrumentation.callApplicationOnCreate(app);//調(diào)用onCreate()方法 }
- 這里找到了為什么使用ContentProvider能夠?qū)崿F(xiàn)初始化,構(gòu)建的時(shí)候會(huì)創(chuàng)建ContenProvider。
- IActivityManager(binder):應(yīng)用進(jìn)程和SystemServer進(jìn)程打交道的時(shí)候。
- AppliactionThread(binder):SystemServer進(jìn)程與應(yīng)用進(jìn)程通信。
2、為什么使用ContentProvider可以實(shí)現(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對(duì)象,調(diào)用onCreate()方法 installContentProviders(app, data.providers); //cotentprovider初始化 mInstrumentation.callApplicationOnCreate(app);//調(diào)用onCreate()方法 }
上一段分析時(shí)已經(jīng)找打了答案,應(yīng)用進(jìn)程被拉起來之后,在創(chuàng)建Application
對(duì)象調(diào)用attachBaseContext()和onCreate()方法之間會(huì)調(diào)用ContentProvider的onCreate()方法這也是很多第三方SDK使用該特性實(shí)現(xiàn)初始化的原理。
3、Activity是什么時(shí)候開始渲染的
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()有這樣一段代碼,我們可以得出結(jié)論,Activity渲染的起點(diǎn)是在
onResume
階段,在onResume階段會(huì)把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啟動(dòng) 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)進(jìn)程(system_server)指揮應(yīng)用進(jìn)程組件生命周期的第一站其實(shí)就在ActivityThread這里,交給H對(duì)象其實(shí)是主線程的Handler來分發(fā)處理,如上。我們可以反射拿到這一信息,可以監(jiān)控到主線程對(duì)于這些組件調(diào)度的信息,這一信息對(duì)我們監(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的以上方法里會(huì)調(diào)用 QueuedWork.waitToFinish();
該代碼會(huì)堵塞主線程執(zhí)行等待SP的寫入操作。這也是SP造成ANR的根源。
稍微展開點(diǎn)
public static void waitToFinish() { while (true) { Runnable finisher; synchronized (sLock) { finisher = sFinishers.poll(); } if (finisher == null) { break; } finisher.run(); } } }
waitToFinish()
方法里有這樣一段代碼,sFinishers是一個(gè)List里面是存放的SP寫入操作,會(huì)在SP執(zhí)行commit
和apply的時(shí)候放入進(jìn)來。字節(jié)跳動(dòng)團(tuán)隊(duì)就是在此處hook了使其poll()
方法永遠(yuǎn)放回空,來杜絕此處產(chǎn)生的ANR。
7 、總結(jié)
通過閱讀ActivityThread的源碼我們能在其中獲取很多有用的知識(shí)。系統(tǒng)進(jìn)程和應(yīng)用進(jìn)程通信的橋梁,Activity真正渲染的起始點(diǎn),ContentProvider
能實(shí)現(xiàn)SDK自動(dòng)初始化的原理等都在ActivityThread
看到他們的影子,希望本文對(duì)你有所啟發(fā)有所幫助。
以上就是Android那兩個(gè)你碰不到但是很重要的類之ActivityThread的詳細(xì)內(nèi)容,更多關(guān)于Android ActivityThread的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android NDK開發(fā)的環(huán)境搭建與簡(jiǎn)單示例
本文主要介紹Android NDK的知識(shí),這里整理了相關(guān)資料,來說明如何搭建相應(yīng)環(huán)境和簡(jiǎn)單實(shí)例,幫助大家理解,有興趣的小伙伴可以參考下2016-09-09Android 實(shí)現(xiàn)無網(wǎng)絡(luò)頁面切換的示例代碼
本篇文章主要介紹了Android 實(shí)現(xiàn)無網(wǎng)絡(luò)頁面切換的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09Android Flutter實(shí)現(xiàn)彈幕效果
這篇文章主要為大家詳細(xì)介紹如何利用Android FLutter實(shí)現(xiàn)彈幕效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06Android使用http請(qǐng)求手機(jī)號(hào)碼歸屬地查詢代碼分享
這篇文章主要介紹了Android使用http請(qǐng)求手機(jī)號(hào)碼歸屬地查詢代碼分享的相關(guān)資料,需要的朋友可以參考下2016-06-06Flutter路由跳轉(zhuǎn)參數(shù)處理技巧詳解
這篇文章主要為大家介紹了Flutter路由跳轉(zhuǎn)參數(shù)處理技巧示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08Android實(shí)現(xiàn)動(dòng)態(tài)自動(dòng)匹配輸入內(nèi)容功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)動(dòng)態(tài)自動(dòng)匹配輸入內(nèi)容功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06關(guān)于Kotlin寫界面時(shí)諸多控件的點(diǎn)擊事件
這篇文章主要介紹了關(guān)于Kotlin寫界面時(shí)諸多控件的點(diǎn)擊事件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-03-03Android實(shí)現(xiàn)Neumorphism?UI控件
大家好,本篇文章主要講的是Android實(shí)現(xiàn)Neumorphism?UI控件,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下2022-02-02