android全方位解析BroadcastReceiver
概念:
作为android的四大,相信很多人都知道broadcastreceiver,那什么是broadcastreceiver ? 直译是“广播接收者”,作用是接受发送过来的广播。那么是广播,举个例子:当我们上课,如果没有听到下课铃声,就不会出去教室,下课。当下课铃声后,我们就知道下课了,广播可以理解是一种消息的传递。再举个例子:我们开机时,会进行一个全局广播,消息是开机启动了,还有网络断开,链接到wifi,电量改变,系统都会作出反应。
android里面的broadcast其实跟我们生活中广播的意思很像,主要是用来消息通信(ipc),android的ipc基本都是binder来实现,而broadcastreceiver其实是对binder的一个封装,方便上层调用,在平时很多时候都是单进程但线程通信,很多人都会用observer或者使用eventbus等来完成功能,的确,它们在这场合效率和灵活性都非常高,但是,broadcastreceiver有自己独有的优势,第一是系统事件的监听,如:开机启动,电量变化;第二多进程通信,如现在多进程保活机制里面就用到了一些系统广播的监听。
原理:
android中的广播使用了设计模式中的观察模式:基于消息的发布/订阅事件模型,而这个模型有三个角色:1.广播接收者,2:广播发送者,3:消息中心(activity manager service),广播接收者通过binder机制在ams注册,广播发送者通过binder机制向ams发送广播,ams根据广播发送者要求,在已注册列表中寻找合适的广播接收者,通过intentfilter来进行刷选。ams将广播发送到合适的广播接收者相应的消息循环队列中,广播接收者通过消息循环拿到广播,并回调onreceiver().注意:广播发送者和广播接收者的执行是异步,发出去的广播不会关心有没有接收者接收,也不知道接收者什么时候能接受到。
具体使用:
1.动态注册
步骤:
1.通过继承broadcastreceiver建立动态广播接收器或者匿名内部类实现
2.实例化intentfilter对象
3.注册广播接收
4.移除广播接收器优化内存空间避免内存溢出
broadcastreceiver mbroadcasrreceive = new broadcastreceiver() { @override public void onreceive(context context, intent intent) { string action = intent.getaction(); if(action.equals(constant.login_success)){ text_send.settext("收到动态广播"); } } };
intentfilter intentfilter = new intentfilter(); intentfilter.addaction(constant.login_success); registerreceiver(mbroadcasrreceive,intentfilter);
@override protected void onpause(){ super.onpause(); unregisterreceiver(mbroadcasrreceive); }
发送广播:
intent mintent = new intent(constant.login_success);
mintent.putextra("yanner","发送广播");
//发送广播
sendbroadcast(mintent);
这样动态方式就可以实现。注意:动态广播最好在activity的onresume()注册,onpause()注销。动态广播,有注册就必然有注销,否则会导致内存泄漏,重复注册和注销都是不允许的。为什么要在onpause()注销呢,因为onpause()在app死亡前一定会被执行,这样保证广播在app死亡前一定会被注销,从而防止内存泄漏。不在onstop()&ondestory()注销因为当系统如果内存不足时要回收activity占用的资源时,activity在执行完onpause()方法后就会被销毁,有些生命周期方法onstop(),ondestory()就不会执行。当再回到此activity时,是从oncreate方法开始执行。所以如果将广播的注销放在onstop(),ondestory()方法里的话,有可能在activity被销毁后还未执行onstop(),ondestory()方法,广播仍未注销,从而导致内存泄漏。,但是onpause()一定会被执行的。
2.静态注册
步骤:
1.继承broadcastreceiver,重写onreceive方法
public class staticreceiver extends broadcastreceiver { @override public void onreceive(context context, intent intent) { if(intent.getaction().equals(constant.register_success)){ toast.maketext(context,"收到静态广播",toast.length_short).show(); } } }
2.在清单文件注册
注意这是自定义广播。
也可以使用系统广播:
以接收短信为例:
public class mybroadcastreceiver extends broadcastreceiver { //action 名称 string sms_received = "android.provider.telephony.sms_received"; @override public void onreceive(context context, intent intent) { if(intent.getaction().equals(sms_received)){ //相关处理 } } }
在androidmanifest.xml中注册
注意还得要添加权限:
两种方式对比
注册方式 | 特点 | 使用场景 |
---|---|---|
静态注册 | 常驻,不受任何组件的生命周期影响,应用程序关闭后,如果有信息广播里,程序依然会被系统调用,但是耗电站内存 | 需要时刻监听广播 |
动态注册 | 不是常驻,灵活,跟随组件的生命周期变化,组件结束 == 广播结束,在组件结束是,必须移除广播接收器 | 需要特定时刻监听广播 |
广播类型及广播的收发
普通广播:
发送一个广播,所以监听该广播的广播接收者都可以监听到该广播
异步广播:
当处理完之后的intent,依然存在,这时候registerreceiver(broadcastreceiver,intentfilter)还能收到他的值,直到把它去掉,不能将处理结果传递给下一个接收者,无法终止广播。
有序广播:
按照接收者的优先级顺序接收广播,优先级别在intent-filter中的priority中声明,-1000到1000之间,值越大,优先级越高,可以终止广播意图的继续传播,接收者可以篡改内容。
有序广播例子:
1.创建两个广播接收者:
public class firstreceiver extends broadcastreceiver { @override public void onreceive(context context, intent intent) { string msg = intent.getstringextra("msg"); log.d("myfirstreceiver", msg); //将数据传输给下一个广播接收者 setresultdata("this is the second msg from myfirstreceiver"); } }
public class secondreceiver extends broadcastreceiver { @override public void onreceive(context context, intent intent) { //获得上一个广播接收者传过来的数据 string msg = getresultdata(); log.d("mythirdreceiver", msg); } }
2.在androidmanifest.xml中注册三个广播接收者
3.发送广播:
intent mintent = new intent("orderbroadcast"); mintent.putextra("yanner","发送广播"); //发送广播 // sendbroadcast(mintent); sendorderedbroadcast(mintent,null);
打印log:
11-15 20:48:49.283 32069-32069/com.example.administrator.broadcastdemo d/11111: this is the first msg from myfirstreceiver
11-15 20:48:49.302 32069-32069/com.example.administrator.broadcastdemo d/1111: this is the second msg from myfirstreceiver
每个接收者都加了一个属性:priority,这个属性表示有序广播中的优先级,值越高表示优先级越高,当广播发出时,优先级最高的便会第一个接收到广播并拦截下来,然后继续往优先级低的传递下去。
总结:
广播接收者接收广播的顺序规则是:
按照priority属性值从大到小排序
priority属性一样时,动态注册广播优先
先接收的广播可以对广播进行拦截,后面接收的广播接收者不再接收到此广播
先接收的广播接收者可以对广播进行修改,后接收的广播接收者将接收到被修改后的广播
终止广播的方法是:abortbroadcast();
推荐阅读
-
Android中执行java命令的方法及java代码执行并解析shell命令
-
Android开发之WebView组件的使用解析
-
Android中使用PULL方式解析XML文件深入介绍
-
Android中BroadcastReceiver(异步接收广播Intent)的使用
-
Android中使用Gson解析JSON数据的两种方法
-
android编程之XML文件解析方法详解(附源码)
-
Android 媒体开发之MediaPlayer状态机接口方法实例解析
-
Android新特性ConstraintLayout完全解析
-
Android解析XML(PULL)展示到ListView
-
Android编程之json解析实例详解