详解基于Binder的BroadcastReceiver && 基于Handler的LocalBroadcastManager

来源:互联网 发布:linux rm 强制删除 编辑:程序博客网 时间:2024/05/29 06:54

一、BroadcastReceiver:

1.registerReceiver动态注册和通过<receiver>标签静态注册广播的区别:
a.对bindService的调用,<receiver>注册的广播,在onReceive结束后广播即不存在,所以不能在其中给自己异步传递结果,如bindService而只能使用startService,如果想跟service交互可使用peekService。
b. 手动控制。registerReceiver为动态注册,自己可以手动注册或是取消注册;<receiver>标签为静态注册,由系统开机时自动扫描注册,所以无法手动控制,开机一直运行中。
c. 资源消耗不同。registerReceiver可以手动控制,所以适当的注册和取消注册能节省系统资源,<receiver>标签系统开机后一直有效。
d.有效期不同。通过registerReceiver注册的BroadcastReceiver在对其进行注册的Context对象"销毁"了或者调用了unregisterReceiver方法时也就失效了,而通过<receiver>标签注册的BroadcastReceiver只要应用程序没有被删除就一直有效。

2.生命周期
BroadcastReceiver在onReceive函数执行结束后即表示生命周期结束,所以不适合在onReceive中做绑定服务操作,结束后若某个进程只含有该BroadcastReceiver,则优先级将降低可能被系统回收,所以BroadcastReceiver中不适合做一些异步操作,如新建线程下载数据,BroadcastReceiver结束后可能在异步操作完成前进程已经被系统kill。
同时由于ANR限制BroadcastReceiver的onReceive函数必须在10秒内完成,而且onReceive默认会在主线程中执行,所以BroadcastReceiver中不适合做一些耗时操作,对于耗时操作需要交给service处理,比如网络或数据库耗时操作、对话框的显示(因为现实时间可能超时,用Notification代替)。

3.安全性
BroadcastReceiver的设计初衷就是从全局考虑的,可以方便应用程序和系统、应用程序之间、应用程序内的通信,所以对单个应用程序而言BroadcastReceiver是存在安全性问题的,相应问题及解决如下:
a、当应用程序发送某个广播时系统会将发送的Intent与系统中所有注册的BroadcastReceiver的IntentFilter进行匹配,若匹配成功则执行相应的onReceive函数。可以通过类似sendBroadcast(Intent, String)的接口在发送广播时指定接收者必须具备的permission。或通过Intent.setPackage设置广播仅对某个程序有效。
b. 当应用程序注册了某个广播时,即便设置了IntentFilter还是会接收到来自其他应用程序的广播进行匹配判断。对于动态注册的广播可以通过类似registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)的接口指定发送者必须具备的permission,对于静态注册的广播可以通过android:exported="false"属性表示接收者对外部应用程序不可用,即不接受来自外部的广播。
c.上面两个问题其实都可以通过LocalBroadcastManager来解决,LocalBroadcastManager只会将广播限定在当前应用程序中.

 

4.有序广播
通过Context.sendOrderedBroadcast发送的广播即为有序广播,与普通广播的不同在于,接收者是有序接收到广播的并且可以对广播进行修改或是取消广播向下传递。系统根据接收者定义的优先级顺序决定哪个接收者先接收到它,接收者处理完后可以将结果传递给优先级低的接收者也可以停止广播使得其他优先级低的接收者无法接收到该广播。优先级通过android:priority属性定义,数值越大优先级别越高,取值范围:-1000到1000

5.Sticky Broadcast粘性广播

如果发送者发送了某个广播,而接收者在这个广播发送后才注册自己的Receiver,这时接收者便无法接收到刚才的广播,为此Android引入了StickyBroadcast,在广播发送结束后会保存刚刚发送的广播(Intent),这样当接收者注册完Receiver后就可以继续使用刚才的广播。如果在接收者注册完成前发送了多条相同Action的粘性广播,注册完成后只会收到一条该Action的广播,并且消息内容是最后一次广播内容。系统网络状态的改变发送的广播就是粘性广播。

粘性广播通过Context的sendStickyBroadcast(Intent)接口发送,需要添加权限<uses-permission android:name="android.permission.BROADCAST_STICKY"/>

也可以通过Context的removeStickyBroadcast(Intent intent)接口移除缓存的粘性广播。

 

二、LocalBroadcastManager

LocalBroadcastManager除了能解决BroadcastReceiver进程间安全性问题外,相对Context操作的BroadcastReceiver而言还具有更高的运行效率。

本地广播通过LocalBroadcastManager.getInstance(context).sendBroadcast(intent)发送广播,LocalBroadcastManager.getInstance(context).registerReceiver注册服务,通过LocalBroadcastManager.getInstance(context).unregisterReceiver取消注册服务,其他同普通广播。

BroadcastReceiver的通信是走 Binder 机制的,LocalBroadcastManager 的核心实现实际还是 Handler,只是利用到了 IntentFilter 的 match 功能,因为是 Handler 实现的应用内的通信,自然安全性更好,效率更高。

 

(1) 自定义 BroadcastReceiver 子类

public class LocalBroadcastReceiver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        localMsg.setText(intent.getStringExtra(MSG_KEY));    }}

 

(2) 注册接收器 

LocalBroadcastReceiver localReceiver = new LocalBroadcastReceiver();LocalBroadcastManager.getInstance(context).registerReceiver(localReceiver, new IntentFilter(ACTION_LOCAL_SEND));


(3) 发送广播

LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(ACTION_LOCAL_SEND));


(4) 取消注册

LocalBroadcastManager.getInstance(context).unregisterReceiver(localReceiver);


 

0 0