成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Android四大組件之BroadcastReceiver全解析

yearsj / 1381人閱讀

摘要:但是,一定會被執(zhí)行,從而保證了廣播在死亡前一定會被注銷,從而防止內(nèi)存泄露。對于應(yīng)用內(nèi)廣播的動態(tài)注冊非方式,回調(diào)中的返回值是

前言

BroadcastReceiver(廣播接收器),屬于Android四大組件之一

在Android開發(fā)中,BroadcastReceiver的應(yīng)用場景非常多

今天,我將詳細(xì)講解關(guān)于BroadcastReceiver的一切相關(guān)知識

目錄

*

1. 定義

廣播,是一個(gè)全局的監(jiān)聽器,屬于Android四大組件之一

Android 廣播分為兩個(gè)角色:廣播發(fā)送者、廣播接收者

2. 作用

用于監(jiān)聽 / 接收 應(yīng)用發(fā)出的廣播消息,并做出響應(yīng)

應(yīng)用場景

不同組件之間通信(包括應(yīng)用內(nèi) / 不同應(yīng)用之間)

Android 系統(tǒng)在特定情況下的通信

如當(dāng)電話呼入時(shí)、網(wǎng)絡(luò)可用時(shí)

多線程通信

3. 實(shí)現(xiàn)原理

Android中的廣播使用了設(shè)計(jì)模式中的觀察者模式:基于消息的發(fā)布/訂閱事件模型。

因此,Android將廣播的發(fā)送者 和 接收者 解耦,使得系統(tǒng)方便集成,更易擴(kuò)展

模型中有3個(gè)角色:

消息訂閱者(廣播接收者)

消息發(fā)布者(廣播發(fā)布者)

消息中心(AMS,即Activity Manager Service

原理描述:

廣播接收者 通過 Binder機(jī)制在 AMS 注冊

廣播發(fā)送者 通過 Binder 機(jī)制向 AMS 發(fā)送廣播

AMS 根據(jù) 廣播發(fā)送者 要求,在已注冊列表中,尋找合適的廣播接收者

> 尋找依據(jù):`IntentFilter / Permission`

AMS將廣播發(fā)送到合適的廣播接收者相應(yīng)的消息循環(huán)隊(duì)列中;

廣播接收者通過 消息循環(huán) 拿到此廣播,并回調(diào) onReceive()

特別注意:廣播發(fā)送者 和 廣播接收者的執(zhí)行 是 異步 的,發(fā)出去的廣播不會關(guān)心有無接收者接收,也不確定接收者到底是何時(shí)才能接收到;

4. 具體使用

具體使用流程如下:

接下來我將一步步介紹如何使用

即上圖中的 開發(fā)者手動完成部分

4.1 自定義廣播接收者BroadcastReceiver

繼承自BroadcastReceivre基類

必須復(fù)寫抽象方法onReceive()方法

> 1.  廣播接收器接收到相應(yīng)廣播后,會自動回調(diào)onReceive()方法
> 2.  一般情況下,onReceive方法會涉及與其他組件之間的交互,如發(fā)送Notification、啟動service等
> 3.  默認(rèn)情況下,廣播接收器運(yùn)行在UI線程,因此,onReceive方法不能執(zhí)行耗時(shí)操作,否則將導(dǎo)致ANR。

代碼范例

_mBroadcastReceiver.java_

public class mBroadcastReceiver extends BroadcastReceiver {

  //接收到廣播后自動調(diào)用該方法
  @Override
  public void onReceive(Context context, Intent intent) {
   //寫入接收廣播后的操作
    }
}
4.2 廣播接收器注冊

注冊的方式分為兩種:靜態(tài)注冊、動態(tài)注冊

4.2.1 靜態(tài)注冊

在AndroidManifest.xml里通過標(biāo)簽聲明

屬性說明:



//用于指定此廣播接收器將接收的廣播類型
//本示例中給出的是用于接收網(wǎng)絡(luò)狀態(tài)改變時(shí)發(fā)出的廣播
 

    

注冊示例


  //用于接收網(wǎng)絡(luò)狀態(tài)改變時(shí)發(fā)出的廣播
  
      
  

當(dāng)此App首次啟動時(shí),系統(tǒng)會**自動**實(shí)例化mBroadcastReceiver類,并注冊到系統(tǒng)中。
4.2.2 動態(tài)注冊

在代碼中通過調(diào)用Context的_registerReceiver()_方法進(jìn)行動態(tài)注冊BroadcastReceiver,具體代碼如下:

@Override
  protected void onResume(){
      super.onResume();

    //實(shí)例化BroadcastReceiver子類 &  IntentFilter
     mBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver();
     IntentFilter intentFilter = new IntentFilter();

    //設(shè)置接收廣播的類型
     intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);

    //調(diào)用Context的registerReceiver()方法進(jìn)行動態(tài)注冊
     registerReceiver(mBroadcastReceiver, intentFilter);
 }

//注冊廣播后,要在相應(yīng)位置記得銷毀廣播
//即在onPause() 中unregisterReceiver(mBroadcastReceiver)
//當(dāng)此Activity實(shí)例化時(shí),會動態(tài)將MyBroadcastReceiver注冊到系統(tǒng)中
//當(dāng)此Activity銷毀時(shí),動態(tài)注冊的MyBroadcastReceiver將不再接收到相應(yīng)的廣播。
 @Override
 protected void onPause() {
     super.onPause();
      //銷毀在onResume()方法中的廣播
     unregisterReceiver(mBroadcastReceiver);
     }
}
特別注意

動態(tài)廣播最好在Activity的onResume()注冊、onPause()注銷。

原因:

對于動態(tài)廣播,有注冊就必然得有注銷,否則會導(dǎo)致內(nèi)存泄露

> 重復(fù)注冊、重復(fù)注銷也不允許

Activity生命周期如下:

Activity生命周期的方法是成對出現(xiàn)的:

onCreate() & onDestory()

onStart() & onStop()

onResume() & onPause()

在onResume()注冊、onPause()注銷是因?yàn)閛nPause()在App死亡前一定會被執(zhí)行,從而保證廣播在App死亡前一定會被注銷,從而防止內(nèi)存泄露。

不在onCreate() & onDestory() 或 onStart() & onStop()注冊、注銷是因?yàn)椋?/p>

當(dāng)系統(tǒng)因?yàn)閮?nèi)存不足(優(yōu)先級更高的應(yīng)用需要內(nèi)存,請看上圖紅框)要回收Activity占用的資源時(shí),Activity在執(zhí)行完onPause()方法后就會被銷毀,有些生命周期方法onStop(),onDestory()就不會執(zhí)行。當(dāng)再回到此Activity時(shí),是從onCreate方法開始執(zhí)行。

假設(shè)我們將廣播的注銷放在onStop(),onDestory()方法里的話,有可能在Activity被銷毀后還未執(zhí)行onStop(),onDestory()方法,即廣播仍還未注銷,從而導(dǎo)致內(nèi)存泄露。

但是,onPause()一定會被執(zhí)行,從而保證了廣播在App死亡前一定會被注銷,從而防止內(nèi)存泄露。

4.2.3 兩種注冊方式的區(qū)別

4.3 廣播發(fā)送者向AMS發(fā)送廣播 4.3.1 廣播的發(fā)送

廣播是用”意圖(Intent)“標(biāo)識

定義廣播的本質(zhì):定義廣播所具備的“意圖(Intent)”

廣播發(fā)送:廣播發(fā)送者將此廣播的”意圖“通過sendBroadcast()方法發(fā)送出去

4.3.2 廣播的類型

廣播的類型主要分為5類:

普通廣播(Normal Broadcast)

系統(tǒng)廣播(System Broadcast)

有序廣播(Ordered Broadcast)

粘性廣播(Sticky Broadcast)

App應(yīng)用內(nèi)廣播(Local Broadcast)

具體說明如下:
1. 普通廣播(Normal Broadcast)
即開發(fā)者自身定義intent的廣播(最常用)。發(fā)送廣播使用如下:

Intent intent = new Intent();
//對應(yīng)BroadcastReceiver中intentFilter的action
intent.setAction(BROADCAST_ACTION);
//發(fā)送廣播
sendBroadcast(intent);

若被注冊了的廣播接收者中注冊時(shí)intentFilter的action與上述匹配,則會接收此廣播(即進(jìn)行回調(diào)onReceive())。如下mBroadcastReceiver則會接收上述廣播


    //用于接收網(wǎng)絡(luò)狀態(tài)改變時(shí)發(fā)出的廣播
    
        
    

若發(fā)送廣播有相應(yīng)權(quán)限,那么廣播接收者也需要相應(yīng)權(quán)限

2. 系統(tǒng)廣播(System Broadcast)

Android中內(nèi)置了多個(gè)系統(tǒng)廣播:只要涉及到手機(jī)的基本操作(如開機(jī)、網(wǎng)絡(luò)狀態(tài)變化、拍照等等),都會發(fā)出相應(yīng)的廣播

每個(gè)廣播都有特定的Intent - Filter(包括具體的action),Android系統(tǒng)廣播action如下:

系統(tǒng)操作 action
監(jiān)聽網(wǎng)絡(luò)變化 android.net.conn.CONNECTIVITY_CHANGE
關(guān)閉或打開飛行模式 Intent.ACTION_AIRPLANE_MODE_CHANGED
充電時(shí)或電量發(fā)生變化 Intent.ACTION_BATTERY_CHANGED
電池電量低 Intent.ACTION_BATTERY_LOW
電池電量充足(即從電量低變化到飽滿時(shí)會發(fā)出廣播 Intent.ACTION_BATTERY_OKAY
系統(tǒng)啟動完成后(僅廣播一次) Intent.ACTION_BOOT_COMPLETED
按下照相時(shí)的拍照按鍵(硬件按鍵)時(shí) Intent.ACTION_CAMERA_BUTTON
屏幕鎖屏 Intent.ACTION_CLOSE_SYSTEM_DIALOGS
設(shè)備當(dāng)前設(shè)置被改變時(shí)(界面語言、設(shè)備方向等) Intent.ACTION_CONFIGURATION_CHANGED
插入耳機(jī)時(shí) Intent.ACTION_HEADSET_PLUG
未正確移除SD卡但已取出來時(shí)(正確移除方法:設(shè)置--SD卡和設(shè)備內(nèi)存--卸載SD卡) Intent.ACTION_MEDIA_BAD_REMOVAL
插入外部儲存裝置(如SD卡) Intent.ACTION_MEDIA_CHECKING
成功安裝APK Intent.ACTION_PACKAGE_ADDED
成功刪除APK Intent.ACTION_PACKAGE_REMOVED
重啟設(shè)備 Intent.ACTION_REBOOT
屏幕被關(guān)閉 Intent.ACTION_SCREEN_OFF
屏幕被打開 Intent.ACTION_SCREEN_ON
關(guān)閉系統(tǒng)時(shí) Intent.ACTION_SHUTDOWN
重啟設(shè)備 Intent.ACTION_REBOOT

注:當(dāng)使用系統(tǒng)廣播時(shí),只需要在注冊廣播接收者時(shí)定義相關(guān)的action即可,并不需要手動發(fā)送廣播,當(dāng)系統(tǒng)有相關(guān)操作時(shí)會自動進(jìn)行系統(tǒng)廣播

3. 有序廣播(Ordered Broadcast)

定義
發(fā)送出去的廣播被廣播接收者按照先后順序接收

有序是針對廣播接收者而言的

廣播接受者接收廣播的順序規(guī)則(同時(shí)面向靜態(tài)和動態(tài)注冊的廣播接受者)

按照Priority屬性值從大-小排序;

Priority屬性相同者,動態(tài)注冊的廣播優(yōu)先;

特點(diǎn)

接收廣播按順序接收

先接收的廣播接收者可以對廣播進(jìn)行截?cái)啵春蠼邮盏膹V播接收者不再接收到此廣播;

先接收的廣播接收者可以對廣播進(jìn)行修改,那么后接收的廣播接收者將接收到被修改后的廣播

具體使用
有序廣播的使用過程與普通廣播非常類似,差異僅在于廣播的發(fā)送方式:

sendOrderedBroadcast(intent);

4. App應(yīng)用內(nèi)廣播(Local Broadcast)

背景
Android中的廣播可以跨App直接通信(exported對于有intent-filter情況下默認(rèn)值為true)

沖突
可能出現(xiàn)的問題:

其他App針對性發(fā)出與當(dāng)前App intent-filter相匹配的廣播,由此導(dǎo)致當(dāng)前App不斷接收廣播并處理;

其他App注冊與當(dāng)前App一致的intent-filter用于接收廣播,獲取廣播具體信息;

即會出現(xiàn)安全性 & 效率性的問題。

解決方案
使用App應(yīng)用內(nèi)廣播(Local Broadcast)

App應(yīng)用內(nèi)廣播可理解為一種局部廣播,廣播的發(fā)送者和接收者都同屬于一個(gè)App。

相比于全局廣播(普通廣播),App應(yīng)用內(nèi)廣播優(yōu)勢體現(xiàn)在:安全性高 & 效率高

具體使用1 - 將全局廣播設(shè)置成局部廣播

注冊廣播時(shí)將exported屬性設(shè)置為_false_,使得非本App內(nèi)部發(fā)出的此廣播不被接收;

在廣播發(fā)送和接收時(shí),增設(shè)相應(yīng)權(quán)限permission,用于權(quán)限驗(yàn)證;

發(fā)送廣播時(shí)指定該廣播接收器所在的包名,此廣播將只會發(fā)送到此包中的App內(nèi)與之相匹配的有效廣播接收器中。

> 通過**intent.setPackage(packageName)**指定報(bào)名

具體使用2 - 使用封裝好的LocalBroadcastManager類
使用方式上與全局廣播幾乎相同,只是注冊/取消注冊廣播接收器和發(fā)送廣播時(shí)將參數(shù)的context變成了LocalBroadcastManager的單一實(shí)例

注:對于LocalBroadcastManager方式發(fā)送的應(yīng)用內(nèi)廣播,只能通過LocalBroadcastManager動態(tài)注冊,不能靜態(tài)注冊

//注冊應(yīng)用內(nèi)廣播接收器
//步驟1:實(shí)例化BroadcastReceiver子類 & IntentFilter mBroadcastReceiver 
mBroadcastReceiver = new mBroadcastReceiver(); 
IntentFilter intentFilter = new IntentFilter(); 

//步驟2:實(shí)例化LocalBroadcastManager的實(shí)例
localBroadcastManager = LocalBroadcastManager.getInstance(this);

//步驟3:設(shè)置接收廣播的類型 
intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);

//步驟4:調(diào)用LocalBroadcastManager單一實(shí)例的registerReceiver()方法進(jìn)行動態(tài)注冊 
localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);

//取消注冊應(yīng)用內(nèi)廣播接收器
localBroadcastManager.unregisterReceiver(mBroadcastReceiver);

//發(fā)送應(yīng)用內(nèi)廣播
Intent intent = new Intent();
intent.setAction(BROADCAST_ACTION);
localBroadcastManager.sendBroadcast(intent);

5. 粘性廣播(Sticky Broadcast)
由于在Android5.0 & API 21中已經(jīng)失效,所以不建議使用,在這里也不作過多的總結(jié)。

5. 特別注意

對于不同注冊方式的廣播接收器回調(diào)OnReceive(Context context,Intent intent)中的context返回值是不一樣的:

對于靜態(tài)注冊(全局+應(yīng)用內(nèi)廣播),回調(diào)onReceive(context, intent)中的context返回值是:ReceiverRestrictedContext;

對于全局廣播的動態(tài)注冊,回調(diào)onReceive(context, intent)中的context返回值是:Activity Context;

對于應(yīng)用內(nèi)廣播的動態(tài)注冊(LocalBroadcastManager方式),回調(diào)onReceive(context, intent)中的context返回值是:Application Context。

對于應(yīng)用內(nèi)廣播的動態(tài)注冊(非LocalBroadcastManager方式),回調(diào)onReceive(context, intent)中的context返回值是:Activity Context;

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/70542.html

相關(guān)文章

  • Android四大組件BroadcastReceiver

    摘要:作為的四大組件之二,其應(yīng)用場景非常多。作用可以監(jiān)聽或接收應(yīng)用或系統(tǒng)發(fā)出的廣播消息,并做出響應(yīng)??梢灾付í?dú)立的進(jìn)程四大組件都可以通過此屬性指定自己的獨(dú)立進(jìn)程。對于應(yīng)用內(nèi)廣播的動態(tài)注冊方式,回調(diào)中的返回值是。 前言 Hi,大家好,又雙見面啦,上一期我們講了如何使用Activity,肯定有不少小伙伴已經(jīng)創(chuàng)建了屬于自己的FirstActivity,那么這一期我們主要為大家介紹第二個(gè)重要組件Br...

    plus2047 評論0 收藏0
  • Android四大組件Service解析

    摘要:四大組件都支持這個(gè)屬性。到目前為止,中總共有三種啟動方式。返回值方法有一個(gè)的返回值,這個(gè)返回值標(biāo)識服務(wù)關(guān)閉后系統(tǒng)的后續(xù)操作。,啟動后的服務(wù)被殺死,不能保證系統(tǒng)一定會重新創(chuàng)建。 1. 簡介 這篇文章會從Service的一些小知識點(diǎn),延伸到Android中幾種常用進(jìn)程間通信方法。 2. 進(jìn)程 ? ? ? ?Service是一種不提供用戶交互頁面但是可以在后臺長時(shí)間運(yùn)行的組件,可以通過在An...

    alaege 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<