【轉】Android 之ActivityThead、ActivityManagerService 與activity的管理和創建


在android中,Activity是四大組件中比較重要的一個(當然其他的也比較重要),那么android中是怎樣管理這些activity的?應用的進程和主線程是怎么創建的,應用的消息循環又是在什么時候創建的?在這篇文章中將詳細介紹:

 

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

 

 

ActivityThread:

ActivityThread主要用來啟動應用程序的主線程,並且管理在應用端跟用戶打交道的activity。在應用端的activity信息全部被存儲在ActivityThread的成員變量mActivities中。

 

[java]  view plain  copy
 
  1. final HashMap<IBinder, ActivityRecord> mActivities= new  HashMap<IBinder, ActivityRecord>();   

 

也就是說,在mActivities中,記錄了應用程序創建的所有activity實例記錄,對應的是ActivityRecord。

ActivityThread是怎么啟動應用程序的呢?ActivityThread中有一個main函數,在這個里面,將啟動應用程序並建立消息循環。在之前也介紹過,系統會為主線程自動創建消息循環。

  

[java]  view plain  copy
 
  1. /*** 應用程序的啟動入口 . ,主線程在啟動的時候系統會自動建立消息循環機制。*/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的一個實例。

 

[java]  view plain  copy
 
  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對象。該對象是activityThread和ActivityManagerService之間的橋梁。

在attach中還做了一件事情,就是通過代理調用attachApplication,並利用binder的transact機制,在ActivityManagerService中建立了ProcessRecord信息。

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

 

ActivityManagerService:

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

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

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

那么在ActivityManagerService的startActivity中,主要做了那些事情?我們來看下里面比較重要的代碼段:

  • 根據activity、ProcessRecord等信息創建HistoryRecord實例r
[c-sharp]  view plain  copy
 
  1. HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,intent, resolvedType, aInfo, mConfiguration,resultRecord, resultWho, requestCode, componentSpecified);  
  • 把r加入到mHistory中。
[c-sharp]  view plain  copy
 
  1. mHistory.add(addPos, r);   
    • activity被加入到mHistory之后,只是說明在服務端可以找到該activity記錄了,但是在客戶端目前還沒有該activity記錄。還需要通過ProcessRecord中的thread(IApplication)變量,調用它的scheduleLaunchActivity方法在ActivityThread中創建新的ActivityRecord記錄(之前我們說過,客戶端的activity是用ActivityRecord記錄的,並放在mActivities中)。
[c-sharp]  view plain  copy
 
  1. app.thread.scheduleLaunchActivity(new Intent(r.intent), r,System.identityHashCode(r),                    r.info, r.icicle, results, newIntents, !andResume,                    isNextTransitionForward());  

涉及的主要類圖:

再來看下ApplicationThread中的scheduleLaunchActivity方法:

 

[c-sharp]  view plain  copy
 
  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(涉及到window、view、windowManager,詳情請看handleResumeActivity()方法和上一篇關於window、WindowManager的介紹)

 

總結:

  1. 在客戶端和服務端分別有一個管理activity的地方,服務端是在mHistory中,處於mHistory棧頂的就是當前處於running狀態的activity,客戶端是在mActivities中。
  2. 在startActivity時,首先會在ActivityManagerService中建立HistoryRecord,並加入到mHistory中,然后通過scheduleLaunchActivity在客戶端創建ActivityRecord記錄並加入到mActivities中。最終在ActivityThread發起請求,進入消息循環,完成activity的啟動和窗口的管理等
  3. from: http://blog.csdn.net/xieqibao/article/details/6570080


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM