目錄
- 思維導(dǎo)圖
- 概述
- 注冊方式
- 靜態(tài)注冊
- 動(dòng)態(tài)注冊
- 廣播分類
- 普通廣播
- 系統(tǒng)廣播
- 有序廣播
- 粘性廣播
- 應(yīng)用內(nèi)廣播
- 參考
思維導(dǎo)圖
概述
在 Android 系統(tǒng)中吠撮,廣播是在組件之間傳遞數(shù)據(jù)的一種機(jī)制,這些組件可以位于不同的進(jìn)程中屁倔,起到進(jìn)程間通信的作用票罐。
BroadcastReceiver 是對(duì)發(fā)送出來的廣播進(jìn)行過濾叉趣、接收和響應(yīng)的組件,首先將要發(fā)送的消息和用于過濾的信息(action该押、category)裝入一個(gè) Intent 對(duì)象疗杉,然后通過調(diào)用 Context.sendBroadcast() 或 Context.sendOrderBoradcast() 方法把 Intent 對(duì)象以廣播形式發(fā)送出去。廣播發(fā)送出去后蚕礼,所有已注冊的 BroadcastReceiver 會(huì)檢查注冊時(shí)的 IntnetFilter 是否與發(fā)送的 Intent 相匹配烟具,若匹配則會(huì)調(diào)用 BroadcastReceiver 的 onReceiver 方法。
BroadcastReceiver 的生命周期很短闻牡,一旦 onReceiver 執(zhí)行完畢净赴,生命周期就結(jié)束了。
注冊方式
廣播的注冊分為靜態(tài)注冊和動(dòng)態(tài)注冊罩润。
不管靜態(tài)注冊還是動(dòng)態(tài)注冊玖翅,首先得有廣播呀:
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (!TextUtils.isEmpty(intent.getStringExtra("name"))){
Toast.makeText(context, intent.getStringExtra("name"), Toast.LENGTH_SHORT).show();
}
}
}
靜態(tài)注冊
靜態(tài)注冊即指在 AndroidManifest 里面注冊。應(yīng)用一旦啟動(dòng)割以,它就會(huì)常駐進(jìn)程金度,不受任何組件的生命周期影響,即使應(yīng)用程序關(guān)閉后严沥,仍能接收廣播猜极,耗電同時(shí)占內(nèi)存。
<receiver android:name=".broadcast.MyBroadcastReceiver"
android:exported="false">
<intent-filter>
<action android:name="demo"/>
</intent-filter>
</receiver>
mButton.setOnClickListener(new ClickListenerWrapper(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("demo");
intent.putExtra("name", "Omooo");
sendBroadcast(intent);
}
}));
注意:
靜態(tài)注冊在 Android 8 上已經(jīng)完全失效了消玄,所以不建議在使用靜態(tài)注冊跟伏。
動(dòng)態(tài)注冊
動(dòng)態(tài)注冊即在代碼中通過調(diào)用 Context.registerReceiver(BroadcastReceiver,IntentFilter) 來注冊,它有幾個(gè)重載方法翩瓜,但是都會(huì)有這兩個(gè)參數(shù)受扳。一般建議在 Activity 的 onResume 注冊,在 onPause 中注銷兔跌,避免內(nèi)存泄露勘高。同時(shí)也不允許重復(fù)注冊、重復(fù)注銷。
private MyBroadcastReceiver mBroadcastReceiver;
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("demo");
mBroadcastReceiver = new MyBroadcastReceiver();
registerReceiver(mBroadcastReceiver, filter);
}
@Override
protected void onStop() {
super.onStop();
unregisterReceiver(mBroadcastReceiver);
}
廣播分類
廣播可以分為五類:普通廣播华望、系統(tǒng)廣播蕊蝗、有序廣播、粘性廣播和應(yīng)用內(nèi)廣播赖舟。
普通廣播
即開發(fā)者自定義的廣播蓬戚,也是最常用的廣播,上面的實(shí)例就是普通廣播建蹄。
系統(tǒng)廣播
Android 中內(nèi)置了多個(gè)系統(tǒng)廣播:只要涉及到手機(jī)的基本操作(如開關(guān)機(jī)碌更、網(wǎng)絡(luò)狀態(tài)變化、拍照等待)洞慎,都會(huì)發(fā)出相應(yīng)的廣播。常用的有:
系統(tǒng)操作 | action |
---|---|
監(jiān)聽網(wǎng)絡(luò)變化 | android.net.conn.CONNECTIVITY_CHANGE |
電池電量低 | Intent.ACTION_BATTERY_LOW |
成功安裝APK | Intent.ACTION_PACKAGE_ |
... | ... |
上面我們自己隨便寫的 action="demo"嘿棘,所以每次發(fā)送廣播需要自己手動(dòng)調(diào)用 sendBroadcast劲腿,這時(shí)候可以攜帶數(shù)據(jù)過去,而系統(tǒng)廣播并不能自己傳遞數(shù)據(jù)鸟妙。
有序廣播
有序是針對(duì)廣播接收者來說的焦人,前面的實(shí)例,廣播發(fā)出去之后重父,所有滿足條件的廣播接收者都能通知接收廣播花椭。有序廣播則是按照廣播接收者的 priority 屬性值從大到小排序依次接收,同 priority 的動(dòng)態(tài)廣播優(yōu)先于靜態(tài)廣播房午。同時(shí)矿辽,前一個(gè)廣播接收器也可以通過調(diào)用 abortBroadcast() 方法截?cái)鄰V播,這樣優(yōu)先級(jí)低的廣播接收者就無法接收到廣播了郭厌,也可以修改數(shù)據(jù)傳遞袋倔,這就帶來了安全性問題。
前面說過折柠,強(qiáng)烈不建議使用靜態(tài)注冊宾娜,而 priority 屬性就是在 xml 文件里面配置的。
發(fā)送有序廣播使用:
sendOrderedBroadcast(Intent intent, String receiverPermission)
粘性廣播
在 Android 5.0 上已經(jīng)失效扇售,不建議使用前塔。
應(yīng)用內(nèi)廣播
之前發(fā)送和接收到的廣播全都是屬于系統(tǒng)全局廣播,即發(fā)出的廣播可以被其他應(yīng)用接收到承冰,而且也可以接收到其他應(yīng)用發(fā)送出的廣播华弓,這樣可能會(huì)有不安全因素。
當(dāng)不需要通過 sendBroadcast 來完成跨應(yīng)用的通信巷懈,那么建議使用 LocalBroadcastManager该抒,將會(huì)是更加高效、安全的方式,并且對(duì)系統(tǒng)帶來的影響也更小凑保。
BroadcastReceiver 采用的 Binder 方式實(shí)現(xiàn)跨進(jìn)程通信冈爹,而 LocalBroadcastManager 使用 Handler 通信機(jī)制。
函數(shù) | 作用 |
---|---|
LocalBroadcastManager.getInstance(this).registerReceiver(BroadcastReceiver,IntentFilter) | 注冊 Receiver |
LocalBroadcastManager.getInstance(this).unregisterReceiver(BroadcastReceiver,IntentFilter) | 注銷 Receiver |
LocalBroadcastManager.getInstance(this).sendBroadcast(Intent) | 發(fā)送異步廣播 |
LocalBroadcastManager.getInstance(this).sendBroadcastSync(Intent) | 發(fā)送同步廣播 |
注意欧引,應(yīng)用內(nèi)廣播只能是動(dòng)態(tài)注冊频伤。