Android交流

Android BroadcastReceiver详解

2021-08-13  本文已影响0人  帅次

Broadcast Receiver是什么

Broadcast Receiver是四大组件之一,是一种广泛运用在应用程序之间传输信息的机制,通过发送Intent来传送我们的数据。


BroadcastReceiver

Broadcast Receiver使用场景

Broadcast Receiver的种类

image

Broadcast Receiver的使用

image

广播的使用包括以下几个步骤:

以上13步骤需要开发者完成,45步骤由Android系统完成。

样例:

4.1静态注册

public class SCCReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e(getClass().getName(),"SCCReceiver,传递内容:"+intent.getStringExtra("scc"));
    }
}
<receiver
    android:name=".SCCReceiver"
    android:enabled="true"
    android:exported="true"/>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical">
    <Button
        android:id="@+id/btn_send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发送静态广播" />
</LinearLayout>
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.btn_send).setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_send:
                Log.e(getClass().getName(),"点击R.id.btn_send");
                Intent intent = new Intent(this, SCCReceiver.class);
                intent.putExtra("scc", "真的帅");
                sendBroadcast(intent);
                break;
        }
    }
}
image

4.2动态广播

public class SCCReceiver2 extends BroadcastReceiver {
    public static final String ACTION = "com.scc.broadcastreceiver.SCCReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e(getClass().getName(),"SCCReceiver2,传递内容:"+intent.getStringExtra("scc"));
    }
}

在代码中通过registerReceiver(BroadcastReceiver receiver, IntentFilter filter)来动态注册广播,该方法包含两个参数,receiver即我们自己定义的SCCReceiver2,IntentFilter即需要过滤的条件。

private SCCReceiver2 sccReceiver2;
@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.btn_reg:
            Log.e(getClass().getName(),"点击R.id.btn_reg");
            if (sccReceiver2 == null) {//防止重复注册
                sccReceiver2 = new SCCReceiver2();
                registerReceiver(sccReceiver2, new IntentFilter(SCCReceiver2.ACTION));
            }
            break;
    }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical">
    <Button
        android:id="@+id/btn_reg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="注册动态广播" />
    <Button
        android:id="@+id/btn_unreg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="注销动态广播" />
    <Button
        android:id="@+id/btn_send_action"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发送动态广播" />
</LinearLayout>
private SCCReceiver2 sccReceiver2;
@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.btn_reg:
            Log.e(getClass().getName(),"点击R.id.btn_reg");
            if (sccReceiver2 == null) {//防止重复注册
                sccReceiver2 = new SCCReceiver2();
                registerReceiver(sccReceiver2, new IntentFilter(SCCReceiver2.ACTION));
            }
            break;
        case R.id.btn_unreg:
            Log.e(getClass().getName(),"点击R.id.btn_unreg");
            if (sccReceiver2 != null) {//防止重复注销
                unregisterReceiver(sccReceiver2);
                sccReceiver2 = null;
            }
            break;
        case R.id.btn_send_action:
            Log.e(getClass().getName(),"点击R.id.btn_send_action");
            Intent intentAction = new Intent(SCCReceiver2.ACTION);
            intentAction.putExtra("scc", "动态,真的帅");
            sendBroadcast(intentAction);
            break;
    }
}
image

使用unregisterReceiver(BroadcastReceiver receiver)来注销注册,动态注册的广播在应用停止运行后无法接收广播,比如在MainActivity中注册,则应当在MainActivity销毁前,使用unregisterReceiver(BroadcastReceiver receiver)来注销注册

对于动态广播注意:

4.3无序广播

无序广播直接通过Context.sendBroadcast()来发送。上面的4.1静态广播和4.2动态广播实现都是无序广播。无序广播被发送后,BroadCastReceiver之间是无顺序,完全异步的,各个Receiver之间无关联。无序广播无法通过abortBroadcast终止,也无法使用setResult和getResult来传递处理结果。

4.4有序广播

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.scc.broadcastreceiver">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.BroadcastReceiverDemo">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/Theme.BroadcastReceiverDemo.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver
            android:name=".SCCReceiver"
            android:enabled="true"
            android:exported="true"/>
        <receiver
            android:name=".SCCReceiver3">
            <intent-filter>
                <action android:name="com.scc.broadcastreceiver.SCCReceiver"/>
            </intent-filter>
        </receiver>
        <receiver
            android:name=".SCCReceiver4">
            <intent-filter>
                <action android:name="com.scc.broadcastreceiver.SCCReceiver"/>
            </intent-filter>
        </receiver>
        <receiver
            android:name=".SCCReceiver5">
            <intent-filter>
                <action android:name="com.scc.broadcastreceiver.SCCReceiver"/>
            </intent-filter>
        </receiver>
    </application>
</manifest>
case R.id.btn_send_ordered:
    Log.e(getClass().getName(),"点击R.id.btn_send_ordered");
    Intent intentActionOrdered = new Intent(SCCReceiver2.ACTION);
    intentActionOrdered.putExtra("scc", "有序,真的牛");
    sendOrderedBroadcast(intentActionOrdered,null);
    break;

运行效果:

SCCReceiver3>SCCReceiver4>SCCReceiver5
<receiver
    android:name=".SCCReceiver3">
    <intent-filter android:priority="-100">
        <action android:name="com.scc.broadcastreceiver.SCCReceiver"/>
    </intent-filter>
</receiver>
<receiver
    android:name=".SCCReceiver4">
    <intent-filter android:priority="0">
        <action android:name="com.scc.broadcastreceiver.SCCReceiver"/>
    </intent-filter>
</receiver>
<receiver
    android:name=".SCCReceiver5">
    <intent-filter android:priority="100">
        <action android:name="com.scc.broadcastreceiver.SCCReceiver"/>
    </intent-filter>
</receiver>

运行效果:

SCCReceiver5(100)>SCCReceiver4(0)>SCCReceiver3(-100)
public class SCCReceiver5 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e(getClass().getName(),"SCCReceiver5,传递内容:"+intent.getStringExtra("scc"));
        Bundle bundle = getResultExtras(true);
        bundle.putString("scc","改了数据");
        setResultExtras(bundle);
    }
}
public class SCCReceiver4 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle = getResultExtras(true);
        String name = bundle.getString("scc");
        Log.e(getClass().getName(),"SCCReceiver4,传递内容:"+name);
        abortBroadcast();
        Log.e(getClass().getName(),"SCCReceiver4,拦截");
    }
}

运行效果:

SCCReceiver5(100)修改数据>SCCReceiver4(0)拦截>没有SCCReceiver3(-100)

Broadcast Receiver实现原理

在Android中,广播的出现是为了组件间的通信。其实在Android中,进程间通信有Binder,而同进程的通信方式就更多了,之所以使用广播,发送者与接受者都不需要知道对方的存在,这样带来的好处便是,系统的各个组件可以松耦合地组织在一起,这样系统就具有高度的可扩展性,容易与其它系统进行集成。

Android中的广播使用了观察者模式:基于消息发布/订阅模式的事件驱动模型。

广播模型中包含三个角色:

  • 消息发布者(广播发布者)
  • 消息中心(AMS,即Activity Manager Service)
  • 消息订阅者(广播接收者)

实现步骤:

整个广播发送与接收过程中,发送者与接收者是异步的,发送者不需要知道是否有接受者,也不需要知道接受者何时收到广播。

LocalBroadcastManager特点

Broadcast Receiver注意事项

上一篇下一篇

猜你喜欢

热点阅读