Android那兩個你碰不到但是很重要的類之ActivityThread
前言
上篇文章我們聊瞭些Android
裡那些我們平時碰不到但很重要的類ViewRootImpl
,這一篇我們就來看看另外那個類ActivityThread。
通過本文能瞭解一下內容
1、和系統進程打交道的橋頭堡
應用進程起來之後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"); }
該方法是一個靜態方法,裡面做瞭重要的兩件事
- 創建瞭讓主線程Looper開始工作,並創建瞭一個Handler
- 給system_server【遞紙條】告訴他聯系方式,告訴sytem_servr進程與應用進程取得聯系可以通過ApplicationThread這個binder。看下面這個代碼
private void attach(boolean system, long startSeq) { final IActivityManager mgr = ActivityManager.getService(); mgr.attachApplication(mAppThread, startSeq);//調用遠端的binder }
- 通過
ActivityManager.getService()
拿到system_server
進程的binder,然後把mAppThread
binder傳遞過去。mAppThread
是ApplicationThread
的一個對象,是ActivityThread的一個內部類。 - 取得聯系後的第一站創建Applicaiton。
private class ApplicationThread extends IApplicationThread.Stub { @Override public final void bindApplication() { sendMessage(H.BIND_APPLICATION, data); }
- 接下來就是H主線程的Hanlder,調用handleBindApplication
private void handleBindApplication(AppBindData data) { Application app; data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo, isSdkSandbox);//內部創建LoadedApk app = data.info.makeApplicationInner(data.restrictedBackupMode, null);//內部創建Applicaiton對象,調用onCreate()方法 installContentProviders(app, data.providers); //cotentprovider初始化 mInstrumentation.callApplicationOnCreate(app);//調用onCreate()方法 }
- 這裡找到瞭為什麼使用ContentProvider能夠實現初始化,構建的時候會創建ContenProvider。
- IActivityManager(binder):應用進程和SystemServer進程打交道的時候。
- AppliactionThread(binder):SystemServer進程與應用進程通信。
2、為什麼使用ContentProvider可以實現初始化
private void handleBindApplication(AppBindData data) { Application app; data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo, isSdkSandbox);//內部創建LoadedApk app = data.info.makeApplicationInner(data.restrictedBackupMode, null);//內部創建Applicaiton對象,調用onCreate()方法 installContentProviders(app, data.providers); //cotentprovider初始化 mInstrumentation.callApplicationOnCreate(app);//調用onCreate()方法 }
上一段分析時已經找打瞭答案,應用進程被拉起來之後,在創建Application
對象調用attachBaseContext()和onCreate()方法之間會調用ContentProvider的onCreate()方法這也是很多第三方SDK使用該特性實現初始化的原理。
3、Activity是什麼時候開始渲染的
public void handleResumeActivity() { performResumeActivity(r, finalStateRequest, reason)//調用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開始執行渲染。
4、原來還可以監控組件的生命周期
class H extends Handler { public static final int RECEIVER = 113; //廣播接收者 @UnsupportedAppUsage public static final int CREATE_SERVICE = 114;//Service創建 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; } } }
系統進程(system_server)指揮應用進程組件生命周期的第一站其實就在ActivityThread這裡,交給H對象其實是主線程的Handler來分發處理,如上。我們可以反射拿到這一信息,可以監控到主線程對於這些組件調度的信息,這一信息對我們監控排查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的以上方法裡會調用 QueuedWork.waitToFinish();
該代碼會堵塞主線程執行等待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執行commit
和apply的時候放入進來。字節跳動團隊就是在此處hook瞭使其poll()
方法永遠放回空,來杜絕此處產生的ANR。
7 、總結
通過閱讀ActivityThread的源碼我們能在其中獲取很多有用的知識。系統進程和應用進程通信的橋梁,Activity真正渲染的起始點,ContentProvider
能實現SDK自動初始化的原理等都在ActivityThread
看到他們的影子,希望本文對你有所啟發有所幫助。
以上就是Android那兩個你碰不到但是很重要的類之ActivityThread的詳細內容,更多關於Android ActivityThread的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- ContentProvider啟動流程示例解析
- Android Service完整實現流程分析
- Android BindService使用案例講解
- Android廣播事件流程與廣播ANR原理深入刨析
- Android 分析實現性能優化之啟動速度優化