1. 程式人生 > >Android 之ActivityThead、ActivityManagerService 與activity的管理和建立

Android 之ActivityThead、ActivityManagerService 與activity的管理和建立

android中,Activity是四大元件中比較重要的一個(當然其他的也比較重要),那麼android中是怎樣管理這些activity的?應用的程序和主執行緒是怎麼建立的,應用的訊息迴圈又是在什麼時候建立的?在這篇文章中將詳細介紹:

先來看下涉及到的類,通過以下類圖對整體先有個大概的印象:

ActivityThread:

ActivityThread主要用來啟動應用程式的主執行緒,並且管理在應用端跟使用者打交道的activity。在應用端的activity資訊全部被儲存在ActivityThread的成員變數mActivities中。

  1. final HashMap<IBinder, ActivityRecord> mActivities= 
    new  HashMap<IBinder, ActivityRecord>();   

也就是說,在mActivities中,記錄了應用程式建立的所有activity例項記錄,對應的是ActivityRecord

ActivityThread是怎麼啟動應用程式的呢?ActivityThread中有一個main函式,在這個裡面,將啟動應用程式並建立訊息迴圈。在之前也介紹過,系統會為主執行緒自動建立訊息迴圈。

  1. /*** 應用程式的啟動入口 . ,主執行緒在啟動的時候系統會自動建立訊息迴圈機制。*/publicstaticfinalvoid main(String[] args) {  SamplingProfilerIntegration.start();  Process.setArgV0(
    "<pre-initialized>");  Looper.prepareMainLooper();  ActivityThread thread = new ActivityThread();  thread.attach(false);  Looper.loop();    if (Process.supportsProcesses()) {     thrownew 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)來初始化應用程式的執行環境,並建立activityThreadActivityManagerService之間的橋mAppThread, mAppThreadIApplicationThread的一個例項。

  1. 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物件。該物件是activityThreadActivityManagerService之間的橋樑。

attach中還做了一件事情,就是通過代理呼叫attachApplication,並利用bindertransact機制,在ActivityManagerService中建立了ProcessRecord資訊。

之後通過該ProcessRecord就可以獲得該ActivityThread中的所有ActivityRecord記錄。下面會介紹。

ActivityManagerService:

ActivityManagerService中,也有一個用來管理activity的地方:mHistory棧,這個mHistory棧裡存放的是服務端的activity記錄HistoryActivity(class HistoryRecord extendsIApplicationToken.Stub)。處於棧頂的就是當前running狀態的activity

我們來看一下ActivitystartActivity方法的請求過程:

從該時序圖中可以看出,Activity.startActivity()方法最終是通過代理類和Binder機制,在ActivityManagerService.startActivity方法中執行的。

那麼在ActivityManagerServicestartActivity中,主要做了那些事情?我們來看下里面比較重要的程式碼段:

  • 根據activityProcessRecord等資訊建立HistoryRecord例項r
  1. HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,intent, resolvedType, aInfo, mConfiguration,resultRecord, resultWho, requestCode, componentSpecified);  

  • r加入到mHistory中。
  1. mHistory.add(addPos, r);   
activity被加入到mHistory之後,只是說明在服務端可以找到該activity記錄了,但是在客戶端目前還沒有該activity記錄。還需要通過ProcessRecord中的threadIApplication)變數,呼叫它的scheduleLaunchActivity方法在ActivityThread中建立新的ActivityRecord記錄(之前我們說過,客戶端的activity是用ActivityRecord記錄的,並放在mActivities中)。
  1. app.thread.scheduleLaunchActivity(new Intent(r.intent), r,System.identityHashCode(r),                    r.info, r.icicle, results, newIntents, !andResume,                    isNextTransitionForward());  

涉及的主要類圖:

再來看下ApplicationThread中的scheduleLaunchActivity方法:

  1. 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(涉及到windowviewwindowManager,詳情請看handleResumeActivity()方法和上一篇關於windowWindowManager的介紹)

總結:

  1. 在客戶端和服務端分別有一個管理activity的地方,服務端是在mHistory中,處於mHistory棧頂的就是當前處於running狀態的activity,客戶端是在mActivities中。
  2. startActivity時,首先會在ActivityManagerService中建立HistoryRecord,並加入到mHistory中,然後通過scheduleLaunchActivity在客戶端建立ActivityRecord記錄並加入到mActivities中。最終在ActivityThread發起請求,進入訊息迴圈,完成activity的啟動和視窗的管理等