淺析調用android的content provider(二)

        上一篇文章(http://blog.csdn.net/chenyufei1013/article/details/6586456)中提到應用程序的管理模型。但是,並未作具體的解釋,所以本文先把這一塊內容稍許解釋下,這對跟蹤Android的Framework代碼會有幫助。

  • 主線程消息循環
  • 概述

        Android 2.3.5的實現中:

  1. 同一個進程中,只有一個JVM,一個ActivityThread.main。
  2. 每個java線程中,最多有一個ActivityThread和Looper。
  3. 每個Looper,可以有多個Handler與之對應。創建Handler的時所在的線程決定了該Handler和那個線程的Looper綁定。
  4. 可以通過Handler來獲取消息和投遞消息。
        主線程(ActivityThread.main)的消息循環是由Looper類來實現的。Looper中處理的是消息,由Message類來封裝。可以通過Handler類來和創建和投遞消息。主線程的大致流程如下:
  1. 初始化Looper環境。
  2. 創建用於管理主線程的ActivityThread對象。除了ActivityThread之外還有一個類是ApplicationThread;可以理解爲ApplicationThread是本進程的服務端,負責處理其它進程的請求的,最終將請求遞交給ActivityThread,由ActivityThread來做具體的事情。此部分本節不作介紹。
  3. 初始化Activity運行環境,並通知相關的後臺服務,比如ActivityManagerService。此部分本節不作介紹。
  4. 進入消息循環。
  5. 去初始化。此部分本節不作介紹。

        具體參見下面的源碼分析:

  • 一個進程、一個JVM、一個ActivityThread.main

        關於這個問題不作太多解析,牽扯到的源碼比較多,具體的參考下面的連個調用序列即可。應用進程都是通過zygote進程fork出來的(啓動應用的流程可以參考這裏),zygote進程接收處理socket消息的循環爲ZygoteConnection.run(),調用到ZygoteInit.main的過程爲:

ZygoteConnection.run
  ZygoteConnection.runOnce
    Zygote.forkAndSpecialize // 此處僅fork和初始化
    ZygoteConnection.handleChildProc // 此處便開始執行
      RuntimeInit.zygoteInit
        Process.invokeStaticMain
          ZygoteInit.MethodAndArgsCaller
            ZygoteInit.main // 此處可以和下面的棧接上。

        ZygoteInit.main調用到Activity.onCreate的棧爲(取自eclipse代碼調試時的棧信息):

HelloOnDrawActivity.onCreate(Bundle) line: 14	
Instrumentation.callActivityOnCreate(Activity, Bundle) line: 1123	
ActivityThread.performLaunchActivity(ActivityThread$ActivityRecord, Intent) line: 2364	
ActivityThread.handleLaunchActivity(ActivityThread$ActivityRecord, Intent) line: 2417	
ActivityThread.access$2100(ActivityThread, ActivityThread$ActivityRecord, Intent) line: 116	
ActivityThread$H.handleMessage(Message) line: 1794	
ActivityThread$H(Handler).dispatchMessage(Message) line: 99	
Looper.loop() line: 123	
ActivityThread.main(String[]) line: 4203	
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]	
Method.invoke(Object, Object...) line: 521	
ZygoteInit$MethodAndArgsCaller.run() line: 791	
ZygoteInit.main(String[]) line: 549	
NativeStart.main(String[]) line: not available [native method]

  • 初始化Looper

        初始化Looper的語句爲Looper.prepareMainLooper()。該函數首先調用prepare():

    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper());

        ThreadLocal和Thread的關係可以簡單描述如下,具體可以參見ThreadLocal.get()的代碼。
        1.同一個線程,不同的ThreadLocal,存儲位置不同。
        2.同一個ThreadLocal,在不同的線程中,存儲位置不同。
        此處由於sThreadLocal是static的,故可認爲只有一個ThreadLocal,那麼每個線程中,ThreadLocal.get到的都是同一份,即每個線程只能有一個Looper,可以通過Looper.myLooper()獲取;Looper.getMainLooper()可以獲取ActivityThread.main中的Looper。
        然後是調用setMainLooper(myLooper());設置爲main Looper。接下來設置標誌位,若支持多進程,則允許main Looper退出。

    if (Process.supportsProcesses()) {
        myLooper().mQueue.mQuitAllowed = false;
    }

  • 進入消息循環

        進入消息循環的語句爲Looper.loop(),該函數主要是獲取當前線程的消息隊列,然後對每條消息調用如下函數:

    msg.target.dispatchMessage(msg);

        實際上是調用Handler的dispatchMessage函數;

    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg); // 處理msg的callback
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) { // 處理Handler的callback
                    return;
                }
            }
            handleMessage(msg); // 處理消息體。此處實際上是調用Handler子類的handleMessage函數。
        }
    }

  • 獲取、發送消息

        若是要往消息循環中發送消息,可以通過Handler類,按如下步驟即可。

        1.初始化Handler。初始化Handler的過程如下:

    mLooper = Looper.myLooper(); // 綁定當前線程的Looper
    if (mLooper == null) { // 沒有則報錯。
        throw new RuntimeException(
            "Can't create handler inside thread that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue; // 綁定消息隊列
    mCallback = null; // 沒callback

        2.獲取消息。獲取消息可以通過Handler.obtainMessage函數
        3.發送消息。發送消息可以通過Handler.sendEmptyMessage等相關函數。


  • 應用進程和ActivityManangerService之間的通信

        應用進程和ActivityManangerService之間的通信是通過IBinder的,IBinder只是一種調用方式罷了,具體的調用內容都是定義在Framework中相關的類中的。IBinder是基於C/S模型的,既然是相互通信,自然應用程序既是服務端又是客戶端。下面分別分析之:

        1. 應用進程作爲客戶端
        當應用進程作爲客戶端時,兩端的通信定義在文件ActivityManagerNative.java中。比如:ActivityThread的初始化方法attach中:

    IActivityManager mgr = ActivityManagerNative.getDefault();
        是通過ActivityManagerNative獲取ActivityManagerService的代理對象ActivityManagerProxy的。

    gDefault = asInterface(b);
        asInterface方法會new一個新的ActivityManagerProxy對象返回給應用進程用。而ActivityManagerProxy中的方法都會調用transact方法,這個方法通過IBinder最終會調到ActivityManagerNative.onTransact方法中。由於ActivityManangerService繼承自ActivityManagerNative,onTransact方法又會掉入ActivityManangerService中實現的IActivityManager接口中,從而完成應用程序對ActivityManangerService的調用。

        2.應用進程作爲服務端

        這個過程和上面是類似的,只是它採用的通信類定義在ApplicationThreadNative.java中。當ActivityManangerService拿到ApplicationThreadProxy對象時,然後會通過IBinder調入了ApplicationThreadNative的onTransact方法中,最終調入了ApplicationThread方法中。跟蹤ApplicationThread中的方法會發現它最終調用瞭如下語句:

    mH.sendMessage(msg);

        實際上是通過上面提到的mH的Handler往主線程的消息循環中發消息。比如:ApplicationThread.scheduleLaunchActivity的方法實際上是向主線程中發送H.LAUNCH_ACTIVITY消息。


發佈了86 篇原創文章 · 獲贊 10 · 訪問量 43萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章