在android中,Activity是四大組件中比較重要的一個(當然其他的也比較重要),那么android中是怎樣管理這些activity的?應用的進程和主線程是怎么創建的,應用的消息循環又是在什么時候創建的?在這篇文章中將詳細介紹:
先來看下涉及到的類,通過以下類圖對整體先有個大概的印象:
ActivityThread:
ActivityThread主要用來啟動應用程序的主線程,並且管理在應用端跟用戶打交道的activity。在應用端的activity信息全部被存儲在ActivityThread的成員變量mActivities中。
- final HashMap<IBinder, ActivityRecord> mActivities= new HashMap<IBinder, ActivityRecord>();
也就是說,在mActivities中,記錄了應用程序創建的所有activity實例記錄,對應的是ActivityRecord。
ActivityThread是怎么啟動應用程序的呢?ActivityThread中有一個main函數,在這個里面,將啟動應用程序並建立消息循環。在之前也介紹過,系統會為主線程自動創建消息循環。
- /*** 應用程序的啟動入口 . ,主線程在啟動的時候系統會自動建立消息循環機制。*/public static final void main(String[] args) { SamplingProfilerIntegration.start(); Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); Looper.loop(); if (Process.supportsProcesses()) { throw new RuntimeException("Main thread loop unexpectedly exited"); } thread.detach(); String name = (thread.mInitialApplication != null) ? thread.mInitialApplication.getPackageName() : "<unknown>";Slog.i(TAG, "Main thread of " + name + " is now exiting"); }
在建立消息循環之前,會通過thread.attach(false)來初始化應用程序的運行環境,並建立activityThread和ActivityManagerService之間的橋mAppThread, mAppThread是IApplicationThread的一個實例。
- android.ddm.DdmHandleAppName.setAppName("<pre-initialized>"); RuntimeInit.setApplicationObject(mAppThread.asBinder()); IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { }
注意:每個應用程序對應着一個ActivityThread實例,應用程序由ActivityThread.main打開消息循環。每個應用程序同時也對應着一個ApplicationThread對象。該對象是activityThread和ActivityManagerService之間的橋梁。
在attach中還做了一件事情,就是通過代理調用attachApplication,並利用binder的transact機制,在ActivityManagerService中建立了ProcessRecord信息。
之后通過該ProcessRecord就可以獲得該ActivityThread中的所有ActivityRecord記錄。下面會介紹。
ActivityManagerService:
在ActivityManagerService中,也有一個用來管理activity的地方:mHistory棧,這個mHistory棧里存放的是服務端的activity記錄HistoryActivity(class HistoryRecord extendsIApplicationToken.Stub)。處於棧頂的就是當前running狀態的activity。
我們來看一下Activity的startActivity方法的請求過程:
從該時序圖中可以看出,Activity.startActivity()方法最終是通過代理類和Binder機制,在ActivityManagerService.startActivity方法中執行的。
那么在ActivityManagerService的startActivity中,主要做了那些事情?我們來看下里面比較重要的代碼段:
- 根據activity、ProcessRecord等信息創建HistoryRecord實例r
- HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,intent, resolvedType, aInfo, mConfiguration,resultRecord, resultWho, requestCode, componentSpecified);
- 把r加入到mHistory中。
- mHistory.add(addPos, r);
- activity被加入到mHistory之后,只是說明在服務端可以找到該activity記錄了,但是在客戶端目前還沒有該activity記錄。還需要通過ProcessRecord中的thread(IApplication)變量,調用它的scheduleLaunchActivity方法在ActivityThread中創建新的ActivityRecord記錄(之前我們說過,客戶端的activity是用ActivityRecord記錄的,並放在mActivities中)。
- app.thread.scheduleLaunchActivity(new Intent(r.intent), r,System.identityHashCode(r), r.info, r.icicle, results, newIntents, !andResume, isNextTransitionForward());
涉及的主要類圖:
再來看下ApplicationThread中的scheduleLaunchActivity方法:
- public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Bundle state, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) { ActivityRecord r = new ActivityRecord(); r.token = token; r.ident = ident; r.intent = intent; r.activityInfo = info; r.state = state; r.pendingResults = pendingResults; r.pendingIntents = pendingNewIntents; r.startsNotResumed = notResumed; r.isForward = isForward; queueOrSendMessage(H.LAUNCH_ACTIVITY, r); }
在這個里面主要是根據服務端返回回來的信息創建客戶端activity記錄ActivityRecord. 並通過Handler發送消息到消息隊列,進入消息循環。在ActivityThread.handleMessage()中處理消息。最終在handleLaunchActivity方法中把ActivityRecord記錄加入到mActivities(mActivities.put(r.token,r))中,並啟動activity(涉及到window、view、windowManager,詳情請看handleResumeActivity()方法和上一篇關於window、WindowManager的介紹)
總結:
- 在客戶端和服務端分別有一個管理activity的地方,服務端是在mHistory中,處於mHistory棧頂的就是當前處於running狀態的activity,客戶端是在mActivities中。
- 在startActivity時,首先會在ActivityManagerService中建立HistoryRecord,並加入到mHistory中,然后通過scheduleLaunchActivity在客戶端創建ActivityRecord記錄並加入到mActivities中。最終在ActivityThread發起請求,進入消息循環,完成activity的啟動和窗口的管理等
- from: http://blog.csdn.net/xieqibao/article/details/6570080