<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                1. ContextImpl registerReceiver分析 registerReceiver函數用于注冊一個動態廣播接收者,該函數在Context.java中聲明。根據本章前面對Context家族的介紹(參考圖6-3),其功能最終將通過ContextImpl類的registerReceiver函數來完成,可直接去看ContextImpl是如何實現此函數的。在SDK中一共定義了兩個同名的registerReceiver函數,其代碼如下: **ContextImpl.java::registerReceiver** ~~~ /* 在SDK中輸出該函數,這也是最常用的函數。當廣播到來時,BroadcastReceiver對象的onReceive 函數將在主線程中被調用 */ public Intent registerReceiver(BroadcastReceiverreceiver, IntentFilter filter) { returnregisterReceiver(receiver, filter, null, null); } /* 功能和前面類似,但增加了兩個參數,分別是broadcastPermission和scheduler,作用有 兩個: 其一:對廣播者的權限增加了控制,只有擁有相應權限的廣播者發出的廣播才能被此接收者接收 其二:BroadcastReceiver對象的onReceiver函數可調度到scheduler所在的線程中執行 */ publicIntent registerReceiver(BroadcastReceiver receiver, IntentFilterfilter, String broadcastPermission, Handler scheduler) { /* 注意,下面所調用函數的最后一個參數為getOuterContext的返回值。前面曾說過,ContextImpl為Context家族中真正干活的對象,而它對外的代理人可以是Application和Activity等, getOuterContext就返回這個對外代理人。一般在Activity中調用registerReceiver函數,故此處getOuterContext返回的對外代理人的類型就是Activity。 */ returnregisterReceiverInternal(receiver, filter, broadcastPermission, scheduler, getOuterContext()); } ~~~ 殊途同歸,最終的功能由registerReceiverInternal來完成,其代碼如下: **ContextImpl.java::registerReceiverInternal** ~~~ privateIntent registerReceiverInternal(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler, Context context) { IIntentReceiver rd = null; if(receiver != null) { //①準備一個IIntentReceiver對象 if(mPackageInfo != null && context != null) { //如果沒有設置scheduler,則默認使用主線程的Handler if (scheduler == null) scheduler= mMainThread.getHandler(); //通過getReceiverDispatcher函數得到一個IIntentReceiver類型的對象 rd = mPackageInfo.getReceiverDispatcher( receiver, context, scheduler, mMainThread.getInstrumentation(), true); } else { if (scheduler == null) scheduler= mMainThread.getHandler(); //直接創建LoadedApk.ReceiverDispatcher對象 rd = new LoadedApk.ReceiverDispatcher(receiver, context, scheduler, null, true).getIIntentReceiver(); }//if (mPackageInfo != null && context != null)結束 }// if(receiver != null)結束 try { //②調用AMS的registerReceiver函數 return ActivityManagerNative.getDefault().registerReceiver( mMainThread.getApplicationThread(),mBasePackageName, rd, filter,broadcastPermission); } ...... } ~~~ 以上代碼列出了兩個關鍵點:其一是準備一個IIntentReceiver對象;其二是調用AMS的registerReceiver函數。 先來看IIntentReceiver,它是一個Interface,圖6-17列出了和它相關的成員圖譜。 :-: ![](http://img.blog.csdn.net/20150803123322284?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖6-17 IIntentReceiver相關成員示意圖 由圖6-17可知: - BroadcastReceiver內部有一個PendingResult類。該類是Android 2.3以后新增的,用于異步處理廣播消息。例如,當BroadcastReceiver收到一個廣播時,其onReceive函數將被調用。一般都是在該函數中直接處理該廣播。不過,當該廣播處理比較耗時,還可采用異步的方式進行處理,即先調用BroadcastReceiver的goAsync函數得到一個PendingResult對象,然后將該對象放到工作線程中去處理,這樣onReceive就可以立即返回而不至于耽誤太長時間(這一點對于onReceive函數被主線程調用的情況尤為有用)。在工作線程處理完這條廣播后,需調用PendingResult的finish函數來完成整個廣播的處理流程。 - 廣播由AMS發出,而接收及處理工作卻在另外一個進程中進行,整個過程一定涉及進程間通信。在圖6-17中,雖然在BroadcastReceiver中定義了一個廣播接收者,但是它與Binder沒有有任何關系,故其并不直接參與進程間通信。與之相反,IIntentReceiver接口則和Binder有密切關系,故可推測廣播的接收是由IIntentReceiver接口來完成的。確實,在整個流程中,首先接收到來自AMS的廣播的將是該接口的Bn端,即LoadedApk.ReceiverDispather的內部類InnerReceiver。 接收廣播的處理將放到本節最后再來分析,下面先來看AMS 的registerReceiver函數。 2. AMS的registerReceiver分析 AMS的registerReceiver函數比較簡單,但是由于其中將出現一些新的變量類型和成員,因此接下來按分兩部分進行分析。 (1) registerReceiver分析之一 registerReceiver的返回值是一個Intent,它指向一個匹配過濾條件(由filter參數指明)的Sticky Intent。即使有多個符合條件的Intent,也只返回一個。 **ActivityManagerService.java::registerReceiver** ~~~ public Intent registerReceiver(IApplicationThreadcaller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, String permission) { synchronized(this) { ProcessRecord callerApp = null; if(caller != null) { callerApp = getRecordForAppLocked(caller); ....... //如果callerApp為null,則拋出異常,即系統不允許未登記照冊的進程注冊 //動態廣播接收者 //檢查調用進程是否有callerPackage的信息,如果沒有,也拋異常 if(callerApp.info.uid != Process.SYSTEM_UID && !callerApp.pkgList.contains(callerPackage)){ throw new SecurityException(......); } }......//if(caller != null)判斷結束 List allSticky = null; //下面這段代碼的功能是從系統中所有Sticky Intent中查詢匹配IntentFilter的Intent, //匹配的Intent保存在allSticky中 Iterator actions = filter.actionsIterator(); if(actions != null) { while (actions.hasNext()) { String action = (String)actions.next(); allSticky = getStickiesLocked(action, filter, allSticky); } } ...... //如果存在sticky的Intent,則選取第一個Intent作為本函數的返回值 Intentsticky = allSticky != null ? (Intent)allSticky.get(0) : null; //如果沒有設置接收者,則直接返回sticky 的intent if(receiver == null) return sticky; //新的數據類型ReceiverList及mRegisteredReceivers成員變量,見下文的解釋 //receiver.asBinder將返回IIntentReceiver的Bp端 ReceiverList rl = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder()); //如果是首次調用,則此處rl的值將為null if (rl== null) { rl =new ReceiverList(this, callerApp, Binder.getCallingPid(), Binder.getCallingUid(),receiver); if (rl.app != null) { rl.app.receivers.add(rl); }else { try { //監聽廣播接收者所在進程的死亡消息 receiver.asBinder().linkToDeath(rl, 0); }...... rl.linkedToDeath = true; }// if(rl.app != null)判斷結束 //將rl保存到mRegisterReceivers中 mRegisteredReceivers.put(receiver.asBinder(), rl); } //新建一個BroadcastFilter對象 BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission); rl.add(bf);//將其保存到rl中 // mReceiverResolver成員變量,見下文解釋 mReceiverResolver.addFilter(bf); ~~~ 以上代碼的流程倒是很簡單,不過其中出現的幾個成員變量和數據類型卻嚴重阻礙了我們的思維活動。先解決它們,BroadcastFilter及相關成員變量如圖6-18所示。 :-: ![](http://img.blog.csdn.net/20150803123341456?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖6-18 BroadcastFilter及相關成員變量 結合代碼,對圖6-18中各數據類型和成員變量的作用及關系的解釋如下: - 在AMS中,BroadcastReceiver的過濾條件由BroadcastFilter表示,該類從IntentFilter派生。由于一個BroadcastReceiver可設置多個過濾條件(即多次為同一個BroadcastReceiver對象調用registerReceiver函數以設置不同的過濾條件),故AMS使用ReceiverList(從ArrayList<BroadcastFilter>派生)這種數據類型來表達這種一對多的關系。 - ReceiverList除了能存儲多個BroadcastFilter外,還應該有成員指向某一個具體BroadcastReceiver,否則如何知道到底是哪個BroadcastReceiver設置的過濾條件呢?前面說過,BroadcastReceiver接收廣播是通過IIntentReceiver接口進行的,故ReceiverList中有receiver成員變量指向IIntentReceiver。 - AMS提供mRegisterReceivers用于保存IIntentReceiver和對應ReceiverList的關系。此外,AMS還提供mReceiverResolver變量用于存儲所有動態注冊的BroadcastReceiver所設置的過濾條件。 清楚這些成員變量和數據類型之間的關系后,接著來分析registerReceiver第二階段的工作。 (2) registerReceiver分析之二 **ActivityManagerService.java::registerReceiver** ~~~ //如果allSticky不為空,則表示有Sticky的Intent,需要立即調度廣播發送 if(allSticky != null) { ArrayList receivers = new ArrayList(); receivers.add(bf); intN = allSticky.size(); for(int i=0; i<N; i++) { Intent intent = (Intent)allSticky.get(i); //為每一個需要發送的廣播創建一個BroadcastRecord(暫稱之為廣播記錄)對象 BroadcastRecord r = new BroadcastRecord(intent, null, null, -1, -1, null,receivers, null, 0, null, null, false, true, true); //如果mParallelBroadcasts當前沒有成員,則需要觸發AMS發送廣播 if (mParallelBroadcasts.size() == 0) scheduleBroadcastsLocked();//向AMS發送BROADCAST_INTENT_MSG消息 //所有非ordered廣播記錄都保存在mParallelBroadcasts中 mParallelBroadcasts.add(r); }//for循環結束 }//if (allSticky != null)判斷結束 returnsticky; }//synchronized結束 } ~~~ 這一階段的工作用一句話就能說清楚:為每一個滿足IntentFilter的Sticky的intent創建一個BroadcastRecord對象,并將其保存到mParllelBroadcasts數組中,最后,根據情況調度AMS發送廣播。 從上邊的描述中可以看出,一旦存在滿足條件的Sticky的Intent,系統需要盡快調度廣播發送。說到這里,想和讀者分享一種在實際工作中碰到的情況。 我們注冊了一個BroadcastReceiver,用于接收USB的連接狀態。在注冊完后,它的onReceiver函數很快就會被調用。當時筆者的一些同事認為是注冊操作觸發USB模塊又發送了一次廣播,卻又感到有些困惑,USB模塊應該根據USB的狀態變化去觸發廣播發送,而不應理會廣播接收者的注冊操作,這到底是怎么一回事呢? 相信讀者現在應該輕松解決這種困惑了吧?對于Sticky的廣播,一旦有接收者注冊,系統會馬上將該廣播傳遞給它們。 和ProcessRecord及ActivityRecord類似,AMS定義了一個BroadcastRecord數據結構,用于存儲和廣播相關的信息,同時還有兩個成員變量,它們作用和關系如圖6-19所示。 :-: ![](http://img.blog.csdn.net/20150803123359357?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖6-19 BroadcastReceiver及相關變量 圖6-19比較簡單,讀者可自行研究。 在代碼中,registerReceiver將調用scheduleBroadcastsLocked函數,通知AMS立即著手開展廣播發送工作,在其內部就發送BROADCAST_INTENT_MSG消息給AMS。相關的處理工作將放到本節最后再來討論。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看