概念:
作為android的四大組件,相信很多人都知道BroadcastReceiver,那什麼是BroadcastReceiver ? 直譯是“廣播接收者”,作用是接受發送過來的廣播。那麼是廣播,舉個例子:當我們上課,如果沒有聽到下課鈴聲,就不會出去教室,下課。當下課鈴聲後,我們就知道下課瞭,廣播可以理解是一種消息的傳遞。再舉個例子:我們開機時,系統會進行一個全局廣播,消息是開機啟動瞭,還有網絡斷開,鏈接到wifi,電量改變,系統都會作出反應。
Android裡面的Broadcast其實跟我們生活中廣播的意思很像,主要是用來消息通信(IPC),Android的IPC基本都是binder來實現,而BroadcastReceiver其實是對binder的一個封裝,方便上層調用,在平時很多時候都是單進程但線程通信,很多人都會用Observer或者使用EventBus等來完成功能,的確,它們在這場合效率和靈活性都非常高,但是,BroadcastReceiver有自己獨有的優勢,第一是系統事件的監聽,如:開機啟動,電量變化;第二多進程通信,如現在多進程保活機制裡面就用到瞭一些系統廣播的監聽。
原理:
Android中的廣播使用瞭設計模式中的觀察模式:基於消息的發佈/訂閱事件模型,而這個模型有三個角色:1.廣播接收者,2:廣播發送者,3:消息中心(Activity Manager Service),廣播接收者通過Binder機制在AMS註冊,廣播發送者通過Binder機制向AMS發送廣播,AMS根據廣播發送者要求,在已註冊列表中尋找合適的廣播接收者,通過IntentFilter來進行刷選。AMS將廣播發送到合適的廣播接收者相應的消息循環隊列中,廣播接收者通過消息循環拿到廣播,並回調onReceiver().註意:廣播發送者和廣播接收者的執行是異步,發出去的廣播不會關心有沒有接收者接收,也不知道接收者什麼時候能接受到。
具體使用:
1.動態註冊
步驟:
1.通過繼承BroadcastReceiver建立動態廣播接收器或者匿名內部類實現
2.實例化IntentFilter對象
3.註冊廣播接收
4.移除廣播接收器優化內存空間避免內存溢出
BroadcastReceiver mBroadcasrReceive = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if(action.equals(Constant.LOGIN_SUCCESS)){ text_send.setText("收到動態廣播"); } } };
IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Constant.LOGIN_SUCCESS); registerReceiver(mBroadcasrReceive,intentFilter);
@Override protected void onPause(){ super.onPause(); unregisterReceiver(mBroadcasrReceive); }
發送廣播:
Intent mintent = new Intent(Constant.LOGIN_SUCCESS);
mintent.putExtra("yanner","發送廣播");
//發送廣播
sendBroadcast(mintent);
這樣動態方式就可以實現。註意:動態廣播最好在Activity的onResume()註冊,onPause()註銷。動態廣播,有註冊就必然有註銷,否則會導致內存泄漏,重復註冊和註銷都是不允許的。為什麼要在onPause()註銷呢,因為onPause()在App死亡前一定會被執行,這樣保證廣播在App死亡前一定會被註銷,從而防止內存泄漏。不在onStop()&onDestory()註銷因為當系統如果內存不足時要回收Activity占用的資源時,Activity在執行完onPause()方法後就會被銷毀,有些生命周期方法onStop(),onDestory()就不會執行。當再回到此Activity時,是從onCreate方法開始執行。所以如果將廣播的註銷放在onStop(),onDestory()方法裡的話,有可能在Activity被銷毀後還未執行onStop(),onDestory()方法,廣播仍未註銷,從而導致內存泄漏。,但是onPause()一定會被執行的。
2.靜態註冊
步驟:
1.繼承BroadcastReceiver,重寫onReceive方法
public class StaticReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if(intent.getAction().equals(Constant.REGISTER_SUCCESS)){ Toast.makeText(context,"收到靜態廣播",Toast.LENGTH_SHORT).show(); } } }
2.在清單文件註冊
註意這是自定義廣播。
也可以使用系統廣播:
以接收短信為例:
public class MyBroadcastReceiver extends BroadcastReceiver { //action 名稱 String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED"; @Override public void onReceive(Context context, Intent intent) { if(intent.getAction().equals(SMS_RECEIVED)){ //相關處理 } } }
在AndroidManifest.xml中註冊
註意還得要添加權限:
兩種方式對比
註冊方式 | 特點 | 使用場景 |
---|---|---|
靜態註冊 | 常駐,不受任何組件的生命周期影響,應用程序關閉後,如果有信息廣播裡,程序依然會被系統調用,但是耗電站內存 | 需要時刻監聽廣播 |
動態註冊 | 不是常駐,靈活,跟隨組件的生命周期變化,組件結束 == 廣播結束,在組件結束是,必須移除廣播接收器 | 需要特定時刻監聽廣播 |
廣播類型及廣播的收發
普通廣播:
發送一個廣播,所以監聽該廣播的廣播接收者都可以監聽到該廣播
異步廣播:
當處理完之後的Intent,依然存在,這時候registerReceiver(BroadcastReceiver,IntentFilter)還能收到他的值,直到把它去掉,不能將處理結果傳遞給下一個接收者,無法終止廣播。
有序廣播:
按照接收者的優先級順序接收廣播,優先級別在intent-filter中的priority中聲明,-1000到1000之間,值越大,優先級越高,可以終止廣播意圖的繼續傳播,接收者可以篡改內容。
有序廣播例子:
1.創建兩個廣播接收者:
public class FirstReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String msg = intent.getStringExtra("msg"); Log.d("MyFirstReceiver", msg); //將數據傳輸給下一個廣播接收者 setResultData("This is the Second Msg From MyFirstReceiver"); } }
public class SecondReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //獲得上一個廣播接收者傳過來的數據 String msg = getResultData(); Log.d("MyThirdReceiver", msg); } }
2.在AndroidManifest.xml中註冊三個廣播接收者
3.發送廣播:
Intent mintent = new Intent("OrderBroadcast"); mintent.putExtra("yanner","發送廣播"); //發送廣播 // sendBroadcast(mintent); sendOrderedBroadcast(mintent,null);
打印log:
11-15 20:48:49.283 32069-32069/com.example.administrator.broadcastdemo D/11111: This is the First Msg From MyFirstReceiver
11-15 20:48:49.302 32069-32069/com.example.administrator.broadcastdemo D/1111: This is the Second Msg From MyFirstReceiver
每個接收者都加瞭一個屬性:priority,這個屬性表示有序廣播中的優先級,值越高表示優先級越高,當廣播發出時,優先級最高的便會第一個接收到廣播並攔截下來,然後繼續往優先級低的傳遞下去。
總結:
廣播接收者接收廣播的順序規則是:
按照priority屬性值從大到小排序
priority屬性一樣時,動態註冊廣播優先
先接收的廣播可以對廣播進行攔截,後面接收的廣播接收者不再接收到此廣播
先接收的廣播接收者可以對廣播進行修改,後接收的廣播接收者將接收到被修改後的廣播
終止廣播的方法是:abortBroadcast();