Broadcast Receiver

380 阅读3分钟

Broadcast Receiver类型:

  • 标准广播(无序广播):是一种完全异步执行的广播,在广播发出后,所有广播接收器几乎会同时接收到这个广播消息,因此没有先后顺序可言,这种广播的效率比较高,同时意味着无法截断.

  • 有序广播:是一种同步执行的广播,在广播发出后,同一个时刻只有一个广播接收器能接收到,当这个广播接收器中的逻辑执行完广播才会传递.所有此时的广播接收器是由先后顺序的,优先级高的广播接收器可以先接收,并且前的广播接收器可以截断正在传递的广播,这样后面的广播接收器就无法接收信息.

动态注册

public class MainActivity extends AppCompatActivity {

    private NetWorkChangeReceiver netWorkChangeReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
         
        IntentFilter intentFilter=new IntentFilter();
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        
        netWorkChangeReceiver = new NetWorkChangeReceiver();
        registerReceiver(netWorkChangeReceiver,intentFilter);
    }

    public class NetWorkChangeReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(MainActivity.this, "网络发生了变化", Toast.LENGTH_SHORT).show();
        }
    }

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

静态注册

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

<receiver
    android:name=".MainActivity.NetWorkChangeReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

public class BootCompleteReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(MainActivity.this, "开机完成", Toast.LENGTH_SHORT).show();
    }
}

发送标准(无序)广播:

 public void sendBroadcast(View view){
        Intent intent=new Intent("android.intent.broadcasttest.MY_BROADCAST");
        sendBroadcast(intent);
    }

发送有序广播:

public void sendBroadcast(View view) {
    Intent intent = new Intent("android.intent.broadcasttest.MY_BROADCAST");
    sendOrderedBroadcast(intent, null);
}

本地广播:

public class MainActivity extends AppCompatActivity {

    private LocalBroadcastManager localBroadcastManager;
    private MyLocalReceiver localReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        localBroadcastManager = LocalBroadcastManager.getInstance(this);
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
        localReceiver = new MyLocalReceiver();
        localBroadcastManager.registerReceiver(localReceiver, intentFilter);
    }

    public void sendLocalBroadcast(View view) {
        Intent intent = new Intent("com.example.broadcasttest.LOCAL_BROADCAST");
        localBroadcastManager.sendBroadcast(intent);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        localBroadcastManager.unregisterReceiver(localReceiver);

    }

    class MyLocalReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(MainActivity.this, "本地广播", Toast.LENGTH_SHORT).show();
        }
    }
}

两者及其接收广播的区别:

  1. 动态注册广播不是常驻型广播,跟随Activity的生命周期。注意在Activity结束前,移除广播接收器。静态注册是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。

  2. 当广播为有序广播时:优先级高的先接收(不分静态和动态)。同优先级的广播接收器,动态优先于静态

  3. 同优先级的同类广播接收器,静态:先扫描的优先于后扫描的,动态:先注册的优先于后注册的。**

  4. 当广播为默认广播时:无视优先级,动态广播接收器优先于静态广播接收器

LocalBroadcastManager源码阅读

为什么需要两个map呢?

private final HashMap<BroadcastReceiver, ArrayList<ReceiverRecord>> mReceiver = new HashMap<>();
private final HashMap<String, ArrayList<ReceiverRecord>> mActions = new HashMap<>();
  • 注册广播的时候,根据receiver对象和action值(不是IntentFilter)分别进行了归类,存在了上述两个集合中。

  • 发送广播的时候,先根据action值找出了所有对应的ReceiverRecord,然后再拿出ReceiverRecord存储的IntentFilter和Intent进行匹配,匹配上的取出其中的receiver,这个流程首先说明了mActions的存在意义,

mReceiver是为了方便取消注册时检索,而mActions是为了方便发送广播时检索。这也是Map相对于List在检索上的优势体现。

本地广播通过Handler来实现发送和分发的异步处理,我们还可以知道本地广播之所以不能跨进程、效率高是因为,其注册、分发等都是通过本地变量完成的,而不像全局广播那样通过binder机制实现。