前言
上篇文章複習總結了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
呼叫完畢後系統就會去銷燬該例項,這樣那個新建的執行緒優先順序就非常低了很容易被殺死,導致達不到我們要效果。有以下兩種方法可以用於解決這種情況。
- 通過在
onReceive
中呼叫goAsync
獲得PendingResult物件以後再開啟子執行緒,在執行結束時呼叫PendingResult.finish。 - 通過在
onReceive
中啟動服務(比如IntentService)執行耗時任務
四、本地廣播和粘性廣播
這兩種廣播都可以使用開源庫EventBus代替