Android四大元件之BroadcastReceiver篇

HFW發表於2019-03-15

前言

上篇文章複習總結了Service的相關知識,現在開始複習BroadcastReceiver。BroadcastReceiver能夠接受系統或者其他App發來的特定廣播,本文先從廣播的傳送開始

一、傳送廣播的兩種方式

1. sendOrderdBroadcast(Intent, String)

傳送有序廣播,優先順序(通過android:priority或者setPriority設定)高的BroadcastReceiver會被優先收到(如果優先順序相同,則動態註冊的優先順序高於靜態註冊的),其可以改變廣播傳遞的內容或者直接中止該廣播(通過呼叫abortBroadcast)

2. sendBroadcast(Intent, String)

傳送無序廣播,忽略廣播接受者的優先順序(因此無法被中止),所有廣播接受者按照一種不確定的順序接收到

二、BroadcastReceiver的兩種註冊方式

1. 靜態註冊

只需要新建一個類繼承BroadcastReceiver,然後在清單檔案application節點下,配置receiver節點即可,例如下面這段程式碼就配置了一個可用於接受飛航模式開關狀態的BroadcastReceiver

<receiver android:name=".MyBroadcastReceiver">
    <intent-filter>
        <action android:name="android.intent.action.AIRPLANE_MODE" />
    </intent-filter>
</receiver>
複製程式碼

靜態註冊的BroadcastReceiver只要應用程式程式沒被殺死就能接受到對應的廣播,但是其沒法接受某些系統的廣播例如螢幕開啟關閉、電量改變等

2. 動態註冊

動態註冊首先需要建立一個派生於BroadcastReceiver的例項,然後再建立一個IntentFilter例項設定該BroadcastReceiver關注哪幾種廣播,最後呼叫registerReceiver註冊廣播,例如以下程式碼就動態註冊了一個BroadcastReceiver

val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION).apply {
    addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED)
}
registerReceiver(br, filter)
複製程式碼

動態註冊可以接受到靜態註冊無法接收到廣播例如螢幕開啟關閉、電量改變等,此外動態註冊的廣播我們在用完以後應該呼叫unregisterReceiver解除註冊,雖然系統也會幫我們解除,但是會列印錯誤

三、使用BroadcastReceiver的注意點

雖然系統規定BroadcastReceiver的onReceive最多執行10秒,但是由於該方法執行於主執行緒所以其實超過5秒就會ANR,如果我們要在onReceiver執行耗時任務裡面就會想到開一個執行緒執行,但是當onReceive呼叫完畢後系統就會去銷燬該例項,這樣那個新建的執行緒優先順序就非常低了很容易被殺死,導致達不到我們要效果。有以下兩種方法可以用於解決這種情況。

  1. 通過在onReceive中呼叫goAsync獲得PendingResult物件以後再開啟子執行緒,在執行結束時呼叫PendingResult.finish。
  2. 通過在onReceive中啟動服務(比如IntentService)執行耗時任務

四、本地廣播和粘性廣播

這兩種廣播都可以使用開源庫EventBus代替

相關文章