BroadcastReceiver 使用詳解

BroadcastReceiver作為Android四大組件之一,即廣播。廣播分為發(fā)送者和接收者。要想使用廣播,首先必須先注冊廣播接收者,然后接著發(fā)送廣播。最后在接收者中處理廣播。
其中廣播接收者需繼承BroadcastReceiver并重寫onReceive來實現(xiàn),onReceive就是最終處理廣播的方法。

注意:Android中規(guī)定了BroadCastReceiver不能處理復(fù)雜長時間的邏輯操作,如果在onReceive方法在10s內(nèi)沒法執(zhí)行完畢,則系統(tǒng)會視之為未響應(yīng)狀態(tài),可能會報ANR錯誤??梢詫⑦@些耗時操作放在Service中開辟子線程去執(zhí)行。

BroadcastReceiver分以下幾個來寫:

  1. 靜態(tài)注冊
  2. 動態(tài)注冊
  3. 有序廣播
  4. 本地廣播
  5. 圖解BroadcastReceiver源碼處理過程

靜態(tài)注冊廣播

靜態(tài)廣播注冊:在AndroidManifest.xml中注冊BroadcastReceiver。
首先定一個廣播接收者StaticReceiver.java

/**
 * <pre>
 *     author: chmj
 *     time  : 2017/8/23
 *     desc  : 廣播接收者,需要繼承BroadcastReceiver,并且重寫onReceive方法。其中intent參數(shù)就是發(fā)送的時候的Intent。
 * </pre>
 */

public class StaticReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //獲取廣播的數(shù)據(jù).
        String msg = intent.getStringExtra("test");
        LogHelper.i("靜態(tài)廣播接收消息....." + msg);
    }
}

接著在在AndroidManifest中注冊:

 <receiver android:name=".activity.broadcastreceiver.staticregist.StaticReceiver">
    <intent-filter>
        <action android:name="com.broadcast.static"/>
    </intent-filter>
</receiver>

注意這里的action,這個屬性是這個廣播的標志。在我們發(fā)送廣播的時候會加入廣播標志,在接收的時候只有改廣播標志對上的才能接收。

在Activity中發(fā)送廣播。

findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        /**
         * 1、通過sendBroadcast將廣播的Intent發(fā)送出去,Intent可以攜帶數(shù)據(jù).
         * 2、setAction表示為intent設(shè)置上一個action,即給這個廣播添加一個標志,
         * 后續(xù)只有和這個標志匹配的廣播接收者才可以收到。
         */
        Intent intent = new Intent();

        //廣播標志. 在靜態(tài)注冊中即在在AndroidManifest中需攔截這個action。
        intent.setAction("com.broadcast.static");
        //數(shù)據(jù).
        intent.putExtra("test","test data 123");
        //發(fā)送廣播
        sendBroadcast(intent);
    }
});

動態(tài)注冊廣播

動態(tài)注冊,即在代碼中注冊,用到IntentFileter這個類包裝Receiver然后通過registerReceiver去注冊。動態(tài)注冊可以反注冊,靜態(tài)注冊的廣播不能取消,一直存在到app退出。一般動態(tài)注冊在onCreate中注冊。在onDestroy中進行反注冊.

同樣定一個廣播接收者DynamicReceiver.java

/**
 * <pre>
 *     author: chmj
 *     time  : 2017/8/23
 *     desc  : 廣播接收者,需要繼承BroadcastReceiver,并且重寫onReceive方法。其中intent參數(shù)就是發(fā)送的時候的Intent。
 * </pre>
 */

public class DynamicReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //獲取廣播的數(shù)據(jù).
        String msg = intent.getStringExtra("test");
        LogHelper.i("動態(tài)廣播接收消息....." + msg);
    }
}

動態(tài)注冊即在代碼中注冊,我們一般在onCreate里面注冊。通過IntentFileter這個類包裝Receiver然后通過registerReceiver去注冊。

private DynamicReceiver mDynamicReceiver;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.test_common_broad_cast_context);
    //包裝Receiver
    IntentFilter intentFilter = new IntentFilter();
    //添加標志
    intentFilter.addAction("com.broadcast.dynamic");
    mDynamicReceiver = new DynamicReceiver();
    //動態(tài)注冊廣播
    registerReceiver(mDynamicReceiver,intentFilter);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    unregisterReceiver(mDynamicReceiver);
}

注冊完,然后發(fā)送廣播。

findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent();

        //廣播標志. 在靜態(tài)注冊中即在在AndroidManifest中需攔截這個action。
        intent.setAction("com.broadcast.dynamic");
        //數(shù)據(jù).
        intent.putExtra("test","test data 123");
        //發(fā)送廣播
        sendBroadcast(intent);
    }
});

有序廣播

上面那兩種廣播發(fā)送方式都是無序的,有序廣播通過sendOrderedBroadcast發(fā)送,而接受者Receiver的Action是同一個,只不過他們通過priority屬性進行優(yōu)先級的判定。priority越大優(yōu)先級越高,優(yōu)先級最高的會第一個攔截廣播并處理,然后才會往下傳遞.

首先我們定義3個廣播接收者:

FirstReceiver

public class FirstReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        String msg = intent.getStringExtra("msg");
        LogHelper.i("This is the First msg from Activity " + msg);

        /**
         * 接著發(fā)送消息,action是一樣的,下面的Receiver根據(jù)priority優(yōu)先級來判斷由誰來接收.
         *
         */
        setResultData("FirstReceiver send msg ");
        setResultCode(100);
    }
}

接收到廣播處理之后,要想在傳數(shù)據(jù)給下一個廣播接收者使用,就用setResultData,setResultExtras等方法。而下一個廣播接收者要想獲取上一個廣播接收者傳過來的信息,就用getResultData,getResultExtras等。

SecondReceiver

public class SecondReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //獲取上一個廣播傳過來的信息
        String msg = getResultData();
        //獲取code
        int code = getResultCode();

        /**
         * getResultExtras:參數(shù)為true的時候如果Bundle是空的,則會創(chuàng)建一個Bundle返回,如果是false,則直接返回Bundle對象.
         */
        Bundle bundle1 = getResultExtras(false);
        Bundle bundle2 = getResultExtras(true);

        LogHelper.i("----idOrderBroadcast----" + isOrderedBroadcast());
        LogHelper.i("---bundle1--" + bundle1 + "  bundle2  " + bundle2);
        LogHelper.i("---msg--" + msg + "  code  " + code);

        Bundle bundle = new Bundle();
        bundle.putString("test","444444");
        setResultExtras(bundle);

    }
}

這里getResultExtras:參數(shù)為true的時候如果Bundle是空的,則會創(chuàng)建一個Bundle返回,如果是false,則直接返回Bundle對象.

ThirdReveiver

public class ThirdReveiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle = getResultExtras(false);
        String msg = bundle.getString("test");

        LogHelper.i("ThirdReveiver msg " + msg);
    }
}

注冊三個廣播接收者

<receiver
    android:name=".activity.broadcastreceiver.orderregist.FirstReceiver">
    <intent-filter android:priority="300">
        <action android:name="com.broadcast.order"/>
    </intent-filter>

</receiver>

<receiver
    android:name=".activity.broadcastreceiver.orderregist.SecondReceiver">
    <intent-filter android:priority="200">
        <action android:name="com.broadcast.order"/>
    </intent-filter>

</receiver>

<receiver
    android:name=".activity.broadcastreceiver.orderregist.ThirdReveiver">
    <intent-filter android:priority="100">
        <action android:name="com.broadcast.order"/>
    </intent-filter>

</receiver>

這里注意priority這個參數(shù),priority值越高越優(yōu)先,在這邊FirstReceiver優(yōu)先級最高,則從activity發(fā)出來的廣播,最先被它攔截處理。

發(fā)送廣播通過sendOrderedBroadcast;

findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent();

        //廣播標志. 在靜態(tài)注冊中即在在AndroidManifest中需攔截這個action。
        intent.setAction("com.broadcast.order");
        //數(shù)據(jù).
        intent.putExtra("test","test data 123");
        //發(fā)送廣播
        sendOrderedBroadcast(intent,null);
    }
});

本地廣播

本地廣播,通過LocalBroadcastManager來注冊,不需要考慮安全問題,因為它只在應(yīng)用內(nèi)部有效。是安全的廣播。

同樣定一個廣播接收者DynamicReceiver

public class DynamicReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //獲取廣播的數(shù)據(jù).
        String msg = intent.getStringExtra("test");
        LogHelper.i("動態(tài)廣播接收消息....." + msg);
    }
}

注冊的時候需通過LocalBroadcastManager來注冊。

private LocalBroadcastManager mLocalBroadcastManager;
private LocalReceiver mLocalReceiver;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.test_common_broad_cast_context);
    mLocalBroadcastManager = LocalBroadcastManager.getInstance(mContext);
    mLocalReceiver = new LocalReceiver();
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("com.broadcast.local");

    //本地廣播注冊.
    mLocalBroadcastManager.registerReceiver(mLocalReceiver,intentFilter);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    mLocalBroadcastManager.unregisterReceiver(mLocalReceiver);
}

發(fā)送廣播也是通過LocalBroadcastManager來發(fā)送。

findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent();

        intent.setAction("com.broadcast.local");
        //數(shù)據(jù).
        intent.putExtra("msg","test data 123");
        //發(fā)送本地廣播需要通過LocalBroadcastManager來發(fā)送.
        mLocalBroadcastManager.sendBroadcast(intent);
    }
});

用三張圖來看看源碼處理廣播的過程。

注冊過程

BroadcastReceiver注冊.jpg

發(fā)送過程

BroadcastReceiver發(fā)送流程.jpg

處理過程

BroadcastReceiver處理流程.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • BroadcastReceiver作為Android四大組件之一,即廣播。廣播分為發(fā)送者和接收者。要想使用廣播,首...
    johnnycmj閱讀 2,978評論 0 0
  • 廣播接收器 是Android的四大組件之一,可見廣播在Android中的重要性; 1. 什么是廣播? 廣播(Bro...
    Lost_Robot閱讀 2,053評論 2 10
  • 一. BroadcastReceiver簡介 1.1 BroadcastReceiver定義(What?) And...
    Marker_Sky閱讀 3,569評論 0 1
  • Volley內(nèi)部使用的是HTTP形式 Volley優(yōu)點: ①網(wǎng)絡(luò)請求可以通過隊列排序 ②網(wǎng)絡(luò)請求可以設(shè)置優(yōu)先級 ③...
    香蕉牛奶丶閱讀 510評論 0 0
  • 有一顆浪的心,但是浪過后,安靜下來有顯得格外的寂寞,想通過各種社交軟件來找到能夠做自己的傾訴對象,但是最后發(fā)現(xiàn)沒有...
    琉璃沫閱讀 194評論 0 0

友情鏈接更多精彩內(nèi)容