Android广播机制之有序广播(Ordered broadca

2021-06-07  本文已影响0人  浅_若清风

前面我们学习了Android的标准广播(Normal broadcasts)发送,本章我们来学习Android的另一种广播发送方式——有序广播(Ordered broadcast)。

定义

有序广播(Ordered broadcast)是一种同步执行的广播,在广播发出后,同一时刻只能有一个广播接收器能够接收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播消息才会继续传递。所以此时的广播接收器是有顺序的,优先级高的广播接收器优先接收到广播消息,并且可以截断正在传递的广播,使后面的广播接收器无法收到广播消息。

工作流程示意图
img_1.png
案例:

在发送广播之前,我们需要定义一个广播接收器(Broadcast Receiver)来接收广播。在这里我们分别创建两个继承于BroadcastReceiver的类MyBroadcastReceiver、MyBroadcastReceiverTwo。在onReceive()处理你接收到的广播内容,在这里我用logd分别打印一下输出的接收器名称,以便观察哪个接收器优先执行。

//接收器1
public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        Log.d("Broadcast received", "onReceive:MyBroadcastReceiver");
    }
}
//接收器2
public class MyBroadcastReceiverTwo extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        Log.d("Broadcast received", "onReceive:MyBroadcastReceiverTwo");
    }
}

我们知道,Android广播接收器有两种注册方式。我们可以用以下任意一种来进行注册。

静态注册

在AndroidManifest.xml文件了,我们可以看到多了两个<receiver>标签,这是因为在创建MyBroadcastReceiver 和MyBroadcastReceiver Two接收器时,系统自动帮我们补全了。分别在两个<receiver>标签里添加<intent-filter></intent-filter>代码

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    ...>
    <application ...>
       <receiver
            android:name=".MyBroadcastReceiverTwo"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="100">
                <action android:name="broadcast" />
            </intent-filter>
        </receiver>
        <receiver
            android:name=".MyBroadcastReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="200">
                <action android:name="broadcast" />
            </intent-filter>
        </receiver>
        <activity android:name=".MainActivity">
            ...
        </activity>
    </application>
</manifest>

我们可以发现,和标准广播的静态注册相比,intent-filter标签里多了个priority属性。priority属性表示优先级,数值越高表示优先级越高。broadcast为自定义的广播名称。

动态注册

在需要接收界面进行注册,代码如下

public class MainActivity extends AppCompatActivity {
    MyBroadcastReceiver receiver;
    MyBroadcastReceiverTwo receiver2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //接收器1
        receiver = new MyBroadcastReceiver();
        IntentFilter intentFilter1 = new IntentFilter("broadcast");
        intentFilter1.setPriority(200);
        registerReceiver(receiver,intentFilter1);
        //接收器2
        receiver2 = new MyBroadcastReceiverTwo();
        IntentFilter intentFilter2 = new IntentFilter("broadcast");
        intentFilter2.setPriority(100);
        registerReceiver(receiver2,intentFilter2);
        //Send broadcast
        Button button = findViewById(R.id.send_button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setAction("broadcast");
                sendOrderedBroadcast(intent,null);
            }
        });
    }
    @Override
    protected void onDestroy(){
        super.onDestroy();
        unregisterReceiver(receiver);
        unregisterReceiver(receiver2);
    }

和标准广播一样,首先我们需要分别创建MyBroadcastReceiver、MyBroadcastReceiverTwo的实例以及它们对应的IntentFilter的实例,并分别给IntentFilter的实例添加一个action:broadcast(接收的广播的名称),然后调用registerReceiver()方法进行注册,并将对应的实例传进去。

广播发送

在上面的代码中,我们看到声明了Button方法,所以我们需要在对应的activity_main.xml文件里新增按钮代码

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <Button
        android:id="@+id/send_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Send Button"
        />
</LinearLayout>

和标准广播发送sendBroadcast(参数1)相比,可以看到发送有序广播的方法为sendOrderedBroadcast(参数1,参数2),参数1仍然为Intent,参数2是一个与权限相关的字符串,在此我们可以把它置成null。

编译结果

编译运行工程,点击Send Button按钮,我们可以在Logcat里查看到接收器的优先级高低。
把intentFilter1、intentFilter2的Priority分别设置为200和100。

2021-06-02 12:13:07.007 6896-6896/com.example.custombroadcast D/Broadcast received: MyBroadcastReceiver
2021-06-02 12:13:07.012 6896-6896/com.example.custombroadcast D/Broadcast received: MyBroadcastReceiverTwo

把intentFilter1、intentFilter2的Priority分别设置为100和200。

2021-06-02 12:15:14.747 7012-7012/com.example.custombroadcast D/Broadcast received: MyBroadcastReceiverTwo
2021-06-02 12:15:14.760 7012-7012/com.example.custombroadcast D/Broadcast received: MyBroadcastReceiver
截断

在这里我们把MyBroadcastReceiver设置成高优先级接收器,在MyBroadcastReceiver的onReceive()方法中调用abortBroadcast()方法,这样就截断了这条广播了。我们在Logcat中看不到打印的MyBroadcastReceiverTwo信息。

2021-06-02 12:23:50.331 7162-7162/com.example.custombroadcast D/Broadcast received: MyBroadcastReceiver
注销

当然,我们最后一定不要忘了取消注册。我们可以通过调用unregisterReceiver()方法来实现。至此,Android的标准广播发送就完成了。

上一篇 下一篇

猜你喜欢

热点阅读