1. 程式人生 > >Android廣播機制一註冊流程

Android廣播機制一註冊流程

Broadcast廣播機制--註冊

                                                                                                        --許棟樑

一、前言

      部落格初開,沒事兒寫寫文章。這是撰寫的第一篇技術性文章。就像你知道我知道的那樣,每個人的第一次都會洋相盡出,漏洞百出。。。但是,那又能怎樣?只有邁出第一步,才能知道自己能走多遠。每篇文章前面都閒扯兩句,一方面,本人不太喜歡開頭就複製貼上原始碼;另一方面,寫技術類文章是相當枯燥的,BB兩句正好緩解緩解。

      好吧,開始寫了!另外多說兩句:不必過分在意細節,不要在小範圍內和原始碼死嗑。因此,本文不想描述動態註冊廣播、靜態註冊廣播;不會去解釋mFgBroadcastQueue、mBgBroadcastQueue的區別和用法。

二、文章結構

                1、設計模式簡介

                2、廣播註冊流程

                3、資料結構解釋

三、正文部分

     1、設計模式簡介

     在介紹具體技術細節之前,我認為還是先要理清整個模組所使用的基本框架結構。搭好架子,才不會陷入無盡的程式碼深淵。站在屋頂,才能一窺全貌。這裡我並不打算描述這些設計模式,而是放在《Android核心原始碼與設計模式》這一部落格分類中具體講解。

     Android中的廣播使用的是釋出訂閱者(Subscribe/Publish)模式,或者說是觀察者模式(這兩個模式是否相同?個人感覺這兩者是相通的)。觀察者模式有兩個主體:被觀察物件

(釋出者),觀察者(訂閱者)。被觀察物件中維護一個觀察者列表。當被觀察物件有變化或者釋出者有內容佈告時,會將這個變化或者佈告通知觀察者(訂閱者)。我們來看一下Android系統廣播機制的觀察者模型。

                                           

從設計模式角度來看:

    1)、觀察者即是使用者程式,每個使用者程式可以定義多個廣播接受器。

    2)、被觀察物件持有和維護多個使用者程式的BroadcastReceiver列表。這個列表由app_process程序中的BroadcastQueue以用AMS(ActivityManagerService)

持有。其它使用者程式通過sendBoradcast()傳送廣播,嚴格來說,這個傳送過程只不過是觀察者模式中的外部輸入,即-----被觀察物件發出通知的觸發條件。

從廣播流程上看:

    廣播整體流程可以分為4個步驟:註冊、外部輸入、遍歷、通知。

    1)、註冊:這裡只涉及到通過registerReceiver()方式註冊的廣播。

    2)、外部輸入:使用者程序或者系統中一些程序通過sendBroadcast()傳送廣播。

    3)、遍歷:查詢匹配的、感興趣的廣播接受器(觀察者)。

    4)、通知:找到後,傳送給目標BroadcastReceiver。

2、廣播註冊流程

如上文所述,這裡只描述通過RegisterReceiver()註冊的廣播過等一下,而通過apk應用程式裡面的AndroidManifest.xml註冊的廣播並不作分析。使用者程序註冊廣播流程時序流程圖如下所示。使用者程序通過registerReceiver呼叫,最後註冊過程會流轉到ActivityManagerProxy中,AMS在使用者程序中的代理。最終的註冊位置還是在遠端程序app_process的AMS中完成。很明顯這裡涉及到程序間通訊,即將註冊轉交給AMS完成。

這裡有沒有必要停下來分析Binder通訊機制?是完全沒有必要的!!!不要一旦遇到某個知識點,就岔開主體跑去分析其它的知識。分析過程不要太擴散,Hold不住的!

                                                      

 在AMS中的廣播註冊過程才是關鍵,這裡似乎必須得貼上一下原始碼才能更好的解釋,但是這裡只複製出核心的程式碼片段。通過下面的流程圖,我們可以清晰的看到,原來mRegisteredeReceivers就是“被觀察物件”ActivityManagerService中持有的“觀察者列表”。我們在unregisterReceiver()中也將看到“觀察者”從這個列表中移除的過程。

      

3、資料結構解釋

這裡有必要解釋流程圖中提到的各種資料結構的用法。

  mRegisteredReceivers,它是一個HashMap,key是IbroadcastReceiver轉化的IBinder物件,value是建立的ReceiverList物件。

我們來看一下mRegisteredReceivers的儲存模型,每個使用者程序中的所有broadcastReceiver都在mRegisteredRecievers中儲存。ReceiverList中記錄了使用者程序的相關資訊,具體資訊是記錄在ProcessRecord(即ReceiverList.app變數中)。

    

mReceiverResolver,將當前註冊的BroadcastReceiver中的過濾器轉化成的BroadcastFilter新增到其中。作用是在傳送廣播的過程中獲取註冊的廣播接收器。因此最終起到“觀察者列表”作用的就是這個資料結構。上面提到的mRegisterReceivers只不過用來快速判斷當前BroadcastReciever是否已經註冊,並存儲相關資訊。

BroadcastQueue,是用來儲存其它使用者(程序)通過sendBroadcast()發過來的廣播,並且排程這些廣播,並將之發給相應的廣播接收器。

四、結論:

               有沒有感覺broadcastReceiver的註冊過程很簡單?