详解Android广播机制

谨以文章记录学习历程,如有错误还请指明。

前言

我们上学时都有过这样的经历,当我们在火车站列车候车室中等待时,每当有某次列车开始检票或者进站上车时,就会播放通知来告知在候车室等待的人们该消息。

为了便于进行系统级别的消息通知,Android引入了一套类似的广播机制,然而比上述情景要灵活得多。此文将对Android广播机制的方方面面做出详尽的介绍。


Android广播机制简介

前面我们提到,Android的广播机制更加的灵活,这是因为Android允许每个应用只对自己感兴趣的广播进行注册,这样该程序就只会收到自己所关心的广播内容。
Android广播分为两个方面:广播发送者广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者广播接收器)。

应用场景

同一应用具有多个进程的不同组件之间的消息通信

  • 不同应用间的组件之间的消息通信
  • 与Android系统在特定情况下的通信
  • 如:系统开机,网络变化等

以上只说明适合广播机制的应用场景,还有一些场景理论上可以使用,但是实际开发没有人这么做:

  • 同一应用内同一组件的消息通信:显然扩展变量的作用域、接口回调、Handler-Message等方式都能更简单的实现。

  • 同一应用内的不同组件之间的消息通信(单个进程):对于简单的的情况,依靠接口的回调方式就可解决;而较为复杂的情况,更推荐直接使用EventBus等。

实现原理

设计模式与模型

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

从设计模式上讲,广播的发送者和接收者极大程度的解耦,使得系统方便集成,容易扩展

模型成员:
  • 消息发布者(广播发布者)
  • 消息订阅者(广播接收者)
  • 消息中心(AMS,Activity Manager Service,一个Android系统中极其重要!的成分,以后我们会详细讲解)

此处我们扩展一下,观察者模式和发布订阅模式的关系

  • 发布订阅模式属于广义上的观察者模式
    前者时最常用的一种观察者模式的实现,且从解耦重用角度上看更优于典型的观察者模式

  • 发布订阅模式加入消息中心,实现发布者和订阅者的解耦

    • 在观察者模式中,观察者需要直接订阅目标事件,在目标发出内容改变的事件后,直接接收事件并作出响应。
    • 在发布订阅模式中,多了一个消息中心,一方面从发布者接收事件,另一方面向订阅者发布事件,订阅者需要从消息中心订阅事件。以此避免发布者和订阅者之间产生依赖关系。

实现流程

  1. 广播接收者BroadcastReceiver通过Binder机制向AMS(Activity Manager Service)进行注册;
  2. 广播发送者通过binder机制向AMS发送广播;
  3. AMS查找符合相应条件(IntentFilter/Permission等)的BroadcastReceiver
  4. AMS将广播发送到上述符合条件的BroadcastReceiver相应的消息循环队列中
  5. BroadcastReceiver通过消息循环执行拿到此广播,回调BroadcastReceiver中的onReceive()方法。

广播发送者和广播接收者的执行是异步的,发出去的广播不会关心有无接收者接收,也不确定接收者到底是何时才能接收到。

BroadcastReceiver

自定义BroadcastReceiver

  • 继承基类BroadcaseReceiver
  • 实现抽象方法onReceive(context, intent)

    • 收到广播后,会自动回调onReceive(..)方法
    • 通常,onReceive(..)方法会涉及到与其他组件的交互,如发送Notification,启动service
    • 默认情况,BroadcaseReceiver运行在UI线程,因此,onReceive(..)方法不能执行耗时操作,否则ANR
  • 简单的自定义Demo:
    MyBroadcastReceiver.java

//继承BroadcastReceiver基类
public class MyBroadcastReceiver extends BroadcastReceiver {
   
    private static final String TAG = "MyBroadcastReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        StringBuilder sb = new StringBuilder();
        sb.append("Action: " + intent.getAction() + "\n");
        sb.append("URI: " + intent.toUri(Intent.URI_INTENT_SCHEME).toString() + "\n");
        String log = sb.toString();
        Log.d(TAG, log);
        Toast.makeText(context, log, Toast.LENGTH_LONG).show();
    }
}

BroadcastReceiver注册类型

1. 静态注册

  • AndroidManifest.xml文件中通过<receiver>进行注册
  • 规则及实例说明:
<receiver
    //BroadcastReceiver子类的类名
    android:name="string"

    //是否使用该BroadcastReceiver
    android:enabled=["true" | "false"]

    //此broadcastReceiver能否接收其他App的发出的广播
    //其默认值是由receiver中有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false
    android:exported=["true" | "false"]

    android:icon="drawable resource"
    android:label="string resource"

   
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值