Android中的有序和無序廣播淺析

BroadcastReceiver所對應的廣播分兩類:無序廣播和有序廣播敛助。

無序廣播即為我們平時經(jīng)常使用的廣播,其主要是通過public abstract void sendBroadcast (Intent intent)方法進行發(fā)送盈魁,并通過intent傳遞數(shù)據(jù)贤牛。代碼示例如下:

Intent nonOrderIntent = new Intent();
nonOrderIntent.setAction(ACTION);
sendBroadcast(nonOrderIntent);

無序廣播會被注冊了的相應的感興趣(intent-filter匹配)接收,且順序是無序的急黎。如果發(fā)送廣播時有相應的權(quán)限要求健提,BroadCastReceiver如果想要接收此廣播琳猫,也需要有相應的權(quán)限。

無序廣播的廣播接收者不可以使用setResultData()方法和abortBroadcast()方法私痹,如果使用了會報錯脐嫂。 但是可以使用getResultData()方法,雖然不報錯紊遵,但是獲取到的數(shù)據(jù)為null账千。但是在一種<u>特殊情況</u>下,getResultData()方法能取到無序廣播傳遞的數(shù)據(jù)暗膜,下文會說明在什么情況下匀奏。

無序廣播不可以被攔截,不可以被終止桦山,不可以被修改,無序廣播任何接收者只要匹配條件都可以接收到醋旦,無優(yōu)先級問題恒水。

如果想通過無序廣播傳遞數(shù)據(jù),則可以調(diào)用intent.putExtra方法傳遞饲齐, 接收者可通過intent.get...接收钉凌,不可通過getResultData接收。

有序廣播主要是通過public abstract void sendOrderedBroadcast (Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)方法進行發(fā)送捂人。代碼示例如下:

Intent intent = new Intent();
intent.setAction(ACTION);
sendOrderedBroadcast(intent, null, new Priority2BroadcastReceiver(), null, Activity.RESULT_OK, "MainActivity發(fā)送了一個有序廣播", null);

先介紹一下public abstract void sendOrderedBroadcast (Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)方法

官網(wǎng)api的參數(shù)解釋:

Parameters
intent The Intent to broadcast; all receivers matching this Intent will receive the broadcast.
receiverPermission String naming a permissions that a receiver must hold in order to receive your broadcast. If null, no permission is required.
resultReceiver Your own BroadcastReceiver to treat as the final receiver of the broadcast.
scheduler  A custom Handler with which to schedule the resultReceiver callback; if null it will be scheduled in the Context's main thread.
initialCode    An initial value for the result code. Often Activity.RESULT_OK.
initialData    An initial value for the result data. Often null.
initialExtras  An initial value for the result extras. Often null.

第一個intent:不多說指定intent御雕,所有廣播接收者的匹配規(guī)則

第二個receiverPermission:指定廣播接收器的權(quán)限矢沿,一般自定義,不常用酸纲,可傳null捣鲸。

第三個resultReceiver:指定一個最終的廣播接收器,相當于finally功能闽坡,不論優(yōu)先級栽惶,最后都要接收一次廣播,而這一次收到的廣播為無序廣播(可以在BroadcastReceiver中通過boolean orderedBroadcast = isOrderedBroadcast()方法驗證)疾嗅,但是卻可以通過getResultData等方法取得數(shù)據(jù)外厂,這就是上面提到的特殊情況。

第四個scheduler:看英文沒怎么看懂什么意思代承,一般傳null汁蝶。

第五個initialCode:指定一個code,一般傳Activity.RESULT_OK论悴。

第六個initialData:傳一個字符串數(shù)據(jù)掖棉。對應的在BroadcastReceiver中通過String resultData = getResultData()取得數(shù)據(jù);通過setResultData("優(yōu)先級為3的setResultData的數(shù)據(jù)")修改數(shù)據(jù)意荤,將數(shù)據(jù)傳給下一個優(yōu)先級較低的BroadcastReceiver啊片;如果在優(yōu)先級較高的BroadcastReceiver中沒有使用setResultData修改數(shù)據(jù),那么優(yōu)先級較低的接收到的數(shù)據(jù)還是最原始的數(shù)據(jù)玖像,即initialData的值紫谷。

第七個initialExtras:傳一個Bundle對象,也就是可以傳多種類型的數(shù)據(jù)捐寥。對應的在BroadcastReceiver中通過Bundle bundle = getResultExtras(false)取得Bundle對象笤昨,然后再通過bundle的各種get方法取得數(shù)據(jù);通過setResultExtras()傳入一個修改過的bundle握恳,將該bundle對象傳給下一個優(yōu)先級較低的BroadcastReceiver瞒窒;如果在優(yōu)先級較高的BroadcastReceiver中沒有使用setResultExtras修改數(shù)據(jù),那么優(yōu)先級較低的接收到的數(shù)據(jù)還是最原始的bundle對象乡洼,即initialExtras的值崇裁。

有序廣播所對應的所有的receiver按照在intent-filter中設置的android:priority屬性依次執(zhí)行,android:priority表示優(yōu)先級束昵,值越大拔稳,其所對應的廣播接收者,越先接收到廣播锹雏。在android:priority相同的情況下巴比,如果廣播接收器是通過靜態(tài)注冊的,則接收到廣播的順序不確定,如果是動態(tài)注冊的轻绞,先注冊的將先收到廣播采记。

有序廣播可以被攔截,?可以在較高優(yōu)先級的接收器中通過abortBroadcast()攔截廣播政勃,這樣就會導致較低優(yōu)先級的接收器無法收到廣播了唧龄,但是sendOrderedBroadcast第三個參數(shù)指定的BroadcastReceiver還是會收到廣播的,而且能獲得數(shù)據(jù)稼病。

有序廣播可以通過原始intent.putExtra這種方式傳遞數(shù)據(jù)給BroadcastReceiver选侨,也能通過sendOrderedBroadcast方法的最后2個參數(shù)傳遞數(shù)據(jù),但是通過第一種方式傳遞的數(shù)據(jù)無法中途修改然走,通過第二種方式傳遞的可以通過上面參數(shù)說明中的方式進行修改援制。

具體驗證方式可通過如下代碼驗證以上結(jié)論:

MainActivity

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

import com.tbc.hsx.testbroadcast.receiver.Priority2BroadcastReceiver;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String ACTION = "com.tbc.hsx.testbroadcast.MainActivity";
    public static final String DATA = "data";
    public static final String ORDER_DATA = "order_data";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });


        findViewById(R.id.send_broadcast_btn).setOnClickListener(this);
        findViewById(R.id.send_ordered_broadcast_btn).setOnClickListener(this);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    Handler handler = new Handler() {
        @Override
        public void dispatchMessage(Message msg) {
            super.dispatchMessage(msg);

        }
    };

    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.send_broadcast_btn) {
            Intent nonOrderIntent = new Intent();
            nonOrderIntent.setAction(ACTION);
            sendBroadcast(nonOrderIntent);
        } else if (view.getId() == R.id.send_ordered_broadcast_btn) {
            Intent intent = new Intent();
            intent.putExtra(DATA, "有序廣播通過intent.putExtra傳遞的數(shù)據(jù)");
            intent.setAction(ACTION);
            Bundle bundle = new Bundle();
            bundle.putString(ORDER_DATA, "有序廣播通過bundle傳遞的數(shù)據(jù)");

            sendOrderedBroadcast(intent, null, new Priority2BroadcastReceiver(), handler, Activity.RESULT_OK, "MainActivity發(fā)送了一個有序廣播", bundle);
        }

    }
}

Priority1BroadcastReceiver

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

/**
 * Created by Doraemon
 * Date: 16/4/27
 * Time: 16:35
 * Summary:優(yōu)先級為1的廣播接收器
 */
public class Priority1BroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

        String resultData = getResultData();//獲取有序廣播的數(shù)據(jù)
        System.out.println("優(yōu)先級為1的接收到的廣播數(shù)據(jù)resultData---->" + resultData);
        setResultData("優(yōu)先級為1的setResultData的數(shù)據(jù)");//修改有序廣播的數(shù)據(jù)
    }
}

Priority2BroadcastReceiver

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import com.tbc.hsx.testbroadcast.MainActivity;

/**
 * Created by Doraemon
 * Date: 16/4/27
 * Time: 16:35
 * Summary:
 */
public class Priority2BroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

        boolean orderedBroadcast = isOrderedBroadcast();

        if (orderedBroadcast) {
            System.out.println("優(yōu)先級為1的接收者接收到的是有序廣播");
        } else {
            System.out.println("優(yōu)先級為1的接收者接收到的是無序廣播");
        }


        Bundle bundle=getResultExtras(false);
        if (bundle != null) {
            String orderData = bundle.getString(MainActivity.ORDER_DATA);
            System.out.println("Priority2BroadcastReceiver-------->" + orderData);
        }

        String resultData = getResultData();//獲取有序廣播的數(shù)據(jù)
        System.out.println("優(yōu)先級為2的接收到的廣播數(shù)據(jù)resultData---->" + resultData);
        setResultData("優(yōu)先級為2的setResultData的數(shù)據(jù)");//修改有序廣播的數(shù)據(jù)
    }
}

Priority3BroadcastReceiver

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import com.tbc.hsx.testbroadcast.MainActivity;

/**
 * Created by Doraemon
 * Date: 16/4/27
 * Time: 16:32
 * Summary:
 */
public class Priority3BroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

        Bundle bundle = getResultExtras(false);
        if (bundle != null) {
            String orderData = bundle.getString(MainActivity.ORDER_DATA);
            System.out.println("Priority3BroadcastReceiver-------->" + orderData);
        }

//        bundle.putString(MainActivity.ORDER_DATA, "優(yōu)先級為3的接收者修改了bundle數(shù)據(jù)");
//        setResultExtras(bundle);

        boolean orderedBroadcast = isOrderedBroadcast();
        if (orderedBroadcast) {
            System.out.println("優(yōu)先級為3的接收者接收到的是有序廣播");
        } else {
            System.out.println("優(yōu)先級為3的接收者接收到的是無序廣播");
        }
        String resultData = getResultData();//獲取有序廣播的數(shù)據(jù)
        System.out.println("優(yōu)先級為3的接收到的廣播數(shù)據(jù)resultData---->" + resultData);
        setResultData("優(yōu)先級為3的setResultData的數(shù)據(jù)");//修改有序廣播的數(shù)據(jù)
//        abortBroadcast();

    }
}

AndroidManifest.xml(BroadcastReceiver注冊部分)

<receiver android:name=".receiver.Priority1BroadcastReceiver">
    <intent-filter android:priority="1">
        <action android:name="com.tbc.hsx.testbroadcast.MainActivity" />
    </intent-filter>
</receiver>
<receiver android:name=".receiver.Priority2BroadcastReceiver">
    <intent-filter android:priority="2">
        <action android:name="com.tbc.hsx.testbroadcast.MainActivity" />
    </intent-filter>
</receiver>

<receiver android:name=".receiver.Priority3BroadcastReceiver">
    <intent-filter android:priority="3">
        <action android:name="com.tbc.hsx.testbroadcast.MainActivity" />
    </intent-filter>
</receiver>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市芍瑞,隨后出現(xiàn)的幾起案子晨仑,更是在濱河造成了極大的恐慌,老刑警劉巖拆檬,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件洪己,死亡現(xiàn)場離奇詭異,居然都是意外死亡竟贯,警方通過查閱死者的電腦和手機答捕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來屑那,“玉大人拱镐,你說我怎么就攤上這事〕旨剩” “怎么了沃琅?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蜘欲。 經(jīng)常有香客問我益眉,道長,這世上最難降的妖魔是什么姥份? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任郭脂,我火速辦了婚禮,結(jié)果婚禮上澈歉,老公的妹妹穿的比我還像新娘展鸡。我一直安慰自己,他們只是感情好闷祥,可當我...
    茶點故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布娱颊。 她就那樣靜靜地躺著,像睡著了一般凯砍。 火紅的嫁衣襯著肌膚如雪箱硕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天悟衩,我揣著相機與錄音剧罩,去河邊找鬼。 笑死座泳,一個胖子當著我的面吹牛惠昔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播挑势,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼镇防,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了潮饱?” 一聲冷哼從身側(cè)響起来氧,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎香拉,沒想到半個月后啦扬,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡凫碌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年扑毡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盛险。...
    茶點故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡瞄摊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出枉层,到底是詐尸還是另有隱情泉褐,我是刑警寧澤,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布鸟蜡,位于F島的核電站膜赃,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏揉忘。R本人自食惡果不足惜跳座,卻給世界環(huán)境...
    茶點故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望泣矛。 院中可真熱鬧疲眷,春花似錦、人聲如沸您朽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至几颜,卻和暖如春倍试,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蛋哭。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工县习, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谆趾。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓躁愿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親沪蓬。 傳聞我的和親對象是個殘疾皇子彤钟,可洞房花燭夜當晚...
    茶點故事閱讀 42,700評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Broadcasts Android apps can send or receive broadcast mes...
    woitaylor閱讀 6,167評論 0 12
  • 廣播接收器 是Android的四大組件之一,可見廣播在Android中的重要性跷叉; 1. 什么是廣播样勃? 廣播(Bro...
    Lost_Robot閱讀 1,934評論 2 10
  • 現(xiàn)實中的廣播:電臺為了傳達一些消息而發(fā)送廣播,通過廣播攜帶要傳達的消息性芬,群眾只要買一個收音機峡眶,就可以收到廣播了。 ...
    stevewang閱讀 4,227評論 0 8
  • 沒有一絲光亮 我在獨自尋找 是高山的巍峨 還是流水的漫長 無聲的世界 我聽見喧囂 物色的世界 我看見紛擾 可是我在...
    李瀟寒閱讀 121評論 0 0
  • 佛說植锉,前世的500次回眸才換來今生的擦肩而過辫樱。一些愿望,如果今生屢屢矚目俊庇,就埋了一個下輩子擦肩而過的伏筆狮暑。我就想,...
    晨曦gy閱讀 106評論 0 1