Android查缺補漏--BroadcastReceiver的類型與使用

來源:互聯網
上載者:User

標籤:manager   class   非同步   測試   複習   runtime   文獻   broadcast   dynamic   

Broadcast 是一種被用於應用內和應用之間傳遞資訊的機制。一個廣播可以對應多個接受者。一個完整的廣播機制,需要具有以下三個要素:

  • 發送廣播的Broadcast
  • 接受廣播的BroadcastReceiver
  • 傳遞資訊的Intent

廣播的註冊分為靜態註冊和動態註冊:

  • 靜態註冊:靜態註冊的廣播是指在AndroidManifest中註冊的廣播,此種廣播在應用安裝時就被系統解析,不需要啟動應用就可以收到相應的廣播。
<receiver android:name=".broadcast.MyBroadcastReceiver">    <intent-filter>        <action android:name="MY_BROADCAST_RECEIVER" />    </intent-filter></receiver>
  • 動態註冊:通過Context.registerReceiver()來實現,不需要時要通過Context.unRegisterReceiver()解除廣播,此種廣播必須應用啟動後才能註冊並接收廣播。

    // 動態註冊廣播接收器registerReceiver(new DynamicBroadcastReceiver(), new IntentFilter(MyBroadcastReceiver.ACTION));

廣播又分為普通廣播、有序廣播、本地廣播和sticky廣播。

一、普通廣播

普通廣播通過Context.sendBroadcast()發送,我們沒有辦法制定Receiver們對於普通廣播的接收順序。理論上所有的接收器(Receiver)接收到廣播的順序不確定,但一般是按照其在AndroidMainfest.xml檔案中註冊的順序(不絕對)。
普通廣播中,接受者不能將處理結果傳遞給下一個接收器,也無法終止廣播的傳播。

如下代碼是一個靜態註冊的廣播樣本:

public class MyBroadcastReceiver extends BroadcastReceiver {    String TAG = MyBroadcastReceiver.class.getSimpleName();    public static final String ACTION = "MY_BROADCAST_RECEIVER";    @Override    public void onReceive(Context context, Intent intent) {        Log.i(TAG, "接收到廣播訊息:" + intent.getStringExtra(BroadcastTestActivity.INTENT_INFO));    }}

然後再AndroidMainfest.xml中註冊這個廣播:

<receiver android:name=".broadcast.MyBroadcastReceiver">    <intent-filter>        <action android:name="MY_BROADCAST_RECEIVER" />    </intent-filter></receiver>

接下來在Activity中調用Context.sendBroadcast()發送廣播就可以了:

Intent intent = new Intent(MyBroadcastReceiver.ACTION);intent.putExtra(INTENT_INFO, "我是一個普通廣播");sendBroadcast(intent);

log如下:

12-08 17:29:44.259 6644-6644/cn.codingblock.androidadvancestudy I/MyBroadcastReceiver: 接收到廣播訊息:我是一個普通廣播
  • 普通廣播的接收已排序的測試
    我們仿照MyBroadcastReciver建立多個接收器,代碼一樣:
/** * 靜態註冊的廣播接收器2 * Created by liuwei on 17/12/7. */public class MyBroadcast2Receiver extends BroadcastReceiver {    String TAG = MyBroadcast2Receiver.class.getSimpleName();    public static final String ACTION = "MY_BROADCAST_RECEIVER";    @Override    public void onReceive(Context context, Intent intent) {        Log.i(TAG, "接收到廣播訊息:" + intent.getStringExtra(BroadcastTestActivity.INTENT_INFO));    }}/** * 靜態註冊的廣播接收器3 * Created by liuwei on 17/12/7. */public class MyBroadcast3Receiver extends BroadcastReceiver {...}/** * 靜態註冊的廣播接收器4 * Created by liuwei on 17/12/7. */public class MyBroadcast4Receiver extends BroadcastReceiver {...}/** * 靜態註冊的廣播接收器5 * Created by liuwei on 17/12/7. */public class MyBroadcast5Receiver extends BroadcastReceiver {...}/** * 靜態註冊的廣播接收器6 * Created by liuwei on 17/12/7. */public class MyBroadcast6Receiver extends BroadcastReceiver {...}

然後在AndroidMainfest.xml中為以上廣播都註冊同一個action

<receiver android:name=".broadcast.MyBroadcastReceiver">    <intent-filter>        <action android:name="MY_BROADCAST_RECEIVER" />    </intent-filter></receiver><receiver android:name=".broadcast.MyBroadcast6Receiver">    <intent-filter>        <action android:name="MY_BROADCAST_RECEIVER" />    </intent-filter></receiver><receiver android:name=".broadcast.MyBroadcast2Receiver">    <intent-filter>        <action android:name="MY_BROADCAST_RECEIVER" />    </intent-filter></receiver><receiver android:name=".broadcast.MyBroadcast3Receiver">    <intent-filter>        <action android:name="MY_BROADCAST_RECEIVER" />    </intent-filter></receiver><receiver android:name=".broadcast.MyBroadcast4Receiver">    <intent-filter>        <action android:name="MY_BROADCAST_RECEIVER" />    </intent-filter></receiver><receiver android:name=".broadcast.MyBroadcast5Receiver">    <intent-filter>        <action android:name="MY_BROADCAST_RECEIVER" />    </intent-filter></receiver>

點擊發送廣播,查看log:

12-08 17:29:44.259 6644-6644/cn.codingblock.androidadvancestudy I/MyBroadcastReceiver: 接收到廣播訊息:我是一個普通廣播12-08 17:29:44.268 6644-6644/cn.codingblock.androidadvancestudy I/MyBroadcast6Receiver: 接收到廣播訊息:我是一個普通廣播12-08 17:29:44.271 6644-6644/cn.codingblock.androidadvancestudy I/MyBroadcast2Receiver: 接收到廣播訊息:我是一個普通廣播12-08 17:29:44.273 6644-6644/cn.codingblock.androidadvancestudy I/MyBroadcast3Receiver: 接收到廣播訊息:我是一個普通廣播12-08 17:29:44.277 6644-6644/cn.codingblock.androidadvancestudy I/MyBroadcast4Receiver: 接收到廣播訊息:我是一個普通廣播12-08 17:29:44.280 6644-6644/cn.codingblock.androidadvancestudy I/MyBroadcast5Receiver: 接收到廣播訊息:我是一個普通廣播
二、有序廣播

在AndroidMainfest.xml中註冊廣播時通過priority(值越優先順序越高)節點為廣播添加優先順序,然後再用Context.sendOrderedBroadcast()發送,接收者們就會按照優先順序順序依次執行。

有序廣播的接收者和給下一個接收者傳遞資料,並且接收者在收到廣播之後可以拋棄廣播,使廣播不再向後傳遞。

為上面6個接收器添加優先順序:

<receiver android:name=".broadcast.MyBroadcastReceiver">    <intent-filter android:priority="1">        <action android:name="MY_BROADCAST_RECEIVER" />    </intent-filter></receiver><receiver android:name=".broadcast.MyBroadcast6Receiver">    <intent-filter android:priority="6">        <action android:name="MY_BROADCAST_RECEIVER" />    </intent-filter></receiver><receiver android:name=".broadcast.MyBroadcast2Receiver">    <intent-filter android:priority="2">        <action android:name="MY_BROADCAST_RECEIVER" />    </intent-filter></receiver><receiver android:name=".broadcast.MyBroadcast3Receiver">    <intent-filter android:priority="3">        <action android:name="MY_BROADCAST_RECEIVER" />    </intent-filter></receiver><receiver android:name=".broadcast.MyBroadcast4Receiver">    <intent-filter android:priority="4">        <action android:name="MY_BROADCAST_RECEIVER" />    </intent-filter></receiver><receiver android:name=".broadcast.MyBroadcast5Receiver">    <intent-filter android:priority="5">        <action android:name="MY_BROADCAST_RECEIVER" />    </intent-filter></receiver>

然後通過sendOrderedBroadcast發送廣播觀察log:

intent = new Intent(MyBroadcastReceiver.ACTION);intent.putExtra(INTENT_INFO, "我是一個有序廣播");sendOrderedBroadcast(intent, null);

log如下:

12-08 18:17:26.455 25919-25919/cn.codingblock.androidadvancestudy I/MyBroadcast6Receiver: 接收到廣播訊息:我是一個有序廣播12-08 18:17:26.462 25919-25919/cn.codingblock.androidadvancestudy I/MyBroadcast5Receiver: 接收到廣播訊息:我是一個有序廣播12-08 18:17:26.464 25919-25919/cn.codingblock.androidadvancestudy I/MyBroadcast4Receiver: 接收到廣播訊息:我是一個有序廣播12-08 18:17:26.465 25919-25919/cn.codingblock.androidadvancestudy I/MyBroadcast3Receiver: 接收到廣播訊息:我是一個有序廣播12-08 18:17:26.466 25919-25919/cn.codingblock.androidadvancestudy I/MyBroadcast2Receiver: 接收到廣播訊息:我是一個有序廣播12-08 18:17:26.467 25919-25919/cn.codingblock.androidadvancestudy I/MyBroadcastReceiver: 接收到廣播訊息:我是一個有序廣播
  • abortBroadcast()拋棄廣播:
    普通的廣播是沒有辦法拋棄的,否則會拋出RuntimeException的異常。

只有有序廣播才可以通過此方法拋棄。我們在MyBroadcast6Receiver中添加abortBroadcast()方法:

public class MyBroadcast6Receiver extends BroadcastReceiver {    String TAG = MyBroadcast6Receiver.class.getSimpleName();    public static final String ACTION = "MY_BROADCAST_RECEIVER";    @Override    public void onReceive(Context context, Intent intent) {        Log.i(TAG, "接收到廣播訊息:" + intent.getStringExtra(BroadcastTestActivity.INTENT_INFO));        abortBroadcast();        Log.i(TAG, "丟棄廣播");    }}

然後點擊發送有序廣播,log如下:

12-08 18:34:27.989 1329-1329/cn.codingblock.androidadvancestudy I/MyBroadcast6Receiver: 接收到廣播訊息:我是一個有序廣播12-08 18:34:27.989 1329-1329/cn.codingblock.androidadvancestudy I/MyBroadcast6Receiver: 丟棄廣播

可以看到廣播已經被丟棄了。

  • setResult()傳遞給下一個接收者結果。
  • getResult()接收上一個接收者的結果。

在MyBroadcast6Receiver中添加setResult方法,在MyBroadcast5Receiver添加getResult方法:

public class MyBroadcast6Receiver extends BroadcastReceiver {    String TAG = MyBroadcast6Receiver.class.getSimpleName();    public static final String ACTION = "MY_BROADCAST_RECEIVER";    @Override    public void onReceive(Context context, Intent intent) {        Log.i(TAG, "接收到廣播訊息:" + intent.getStringExtra(BroadcastTestActivity.INTENT_INFO));//        abortBroadcast();//        Log.i(TAG, "丟棄廣播");        setResult(006, "我是老6傳來的訊息", null);    }}public class MyBroadcast5Receiver extends BroadcastReceiver {    String TAG = MyBroadcast5Receiver.class.getSimpleName();    public static final String ACTION = "MY_BROADCAST_RECEIVER";    @Override    public void onReceive(Context context, Intent intent) {        Log.i(TAG, "接收到廣播訊息:" + intent.getStringExtra(BroadcastTestActivity.INTENT_INFO));        String data = getResultData();        Log.i(TAG, "data=" + data);    }}

log如下:

12-08 18:40:01.415 10372-10372/cn.codingblock.androidadvancestudy I/MyBroadcast6Receiver: 接收到廣播訊息:我是一個有序廣播12-08 18:40:01.434 10372-10372/cn.codingblock.androidadvancestudy I/MyBroadcast5Receiver: 接收到廣播訊息:我是一個有序廣播12-08 18:40:01.434 10372-10372/cn.codingblock.androidadvancestudy I/MyBroadcast5Receiver: data=我是老6傳來的訊息12-08 18:40:01.440 10372-10372/cn.codingblock.androidadvancestudy I/MyBroadcast4Receiver: 接收到廣播訊息:我是一個有序廣播12-08 18:40:01.442 10372-10372/cn.codingblock.androidadvancestudy I/MyBroadcast3Receiver: 接收到廣播訊息:我是一個有序廣播12-08 18:40:01.445 10372-10372/cn.codingblock.androidadvancestudy I/MyBroadcast2Receiver: 接收到廣播訊息:我是一個有序廣播12-08 18:40:01.447 10372-10372/cn.codingblock.androidadvancestudy I/MyBroadcastReceiver: 接收到廣播訊息:我是一個有序廣播
三、本地廣播

以上的廣播對於系統來說是全域的,發出廣播後,系統內的應用只要註冊了相應的接收器就都可以收到廣播。如果我們想在本應用發出的廣播只在此應用內可以收到,那麼可以使用本地廣播了。

本地廣播由 LocalBroadcastManager 管理,是在 API 21 以後添加的,使用起來也很方便,需要先通過 LocalBroadcastManager.getInstance() 方法擷取其單例,剩下的用法與其他廣播類似,其主要方法有以下幾個:

  • registerReceiver():註冊廣播接收器。
  • unregisterReceiver():解除廣播接收器。
  • sendBroadcast():發送非同步廣播。
  • sendBroadcastSync():發送同步廣播。

使用本地廣播時,無需在AndroidMainfest.xml中註冊,必須使用 LocalBroadcastManager.getInstance(...).registerReceiver(..)來註冊接收器。

我們來寫個本地廣播的小栗子,首先註冊兩個本地廣播:

LocalBroadcastManager.getInstance(context).registerReceiver(new MyBroadcastReceiver(), new IntentFilter(MyBroadcastReceiver.ACTION));LocalBroadcastManager.getInstance(context).registerReceiver(new MyBroadcast2Receiver(), new IntentFilter(MyBroadcastReceiver.ACTION));

然後發送本地廣播:

intent.putExtra(INTENT_INFO, "我是一個本地廣播");LocalBroadcastManager.getInstance(context).sendBroadcast(intent);

log如下:

12-09 17:20:47.799 15019-15019/cn.codingblock.androidadvancestudy I/MyBroadcastReceiver: 接收到廣播訊息:我是一個本地廣播12-09 17:20:47.799 15019-15019/cn.codingblock.androidadvancestudy I/MyBroadcast2Receiver: 接收到廣播訊息:我是一個本地廣播
四、sticky廣播(不建議使用)

sticky廣播會一直處於滯留狀態,sticky廣播被發出後,只要有能夠匹配其的新接收器被註冊了就可以收到廣播,sticky廣播通過Context.sendStickyBroadcast()發送。

最後想說的是,本系列文章為博主對Android知識進行再次梳理,查缺補漏的學習過程,一方面是對自己遺忘的東西加以複習重新掌握,另一方面相信在重新學習的過程中定會有巨大的新收穫,如果你也有跟我同樣的想法,不妨關注我一起學習,互相探討,共同進步!

參考文獻:

  • 《Android開發藝術探索》
  • 《Android開發進階從小工到專家》

Android查缺補漏--BroadcastReceiver的類型與使用

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.