本地广播介绍
LocalBroadcastManager是Android Support包提供了一个工具,是用来在同一个应用内的不同组件间发送Broadcast的。
使用LocalBroadcastManager有如下好处:
1
2
31. 发送的广播只会在自己App内传播,不会泄露给其他App,确保隐私数据不会泄露 2. 其他App也无法向你的App发送该广播,不用担心其他App会来搞破坏比系统全局广播更加高效
使用方式
先通过
1
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
获取实例,然后通过函数 registerReceiver来注册监听器
1
2
3
4
5
6
7
lbm.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Handle the received local broadcast
}
}, new IntentFilter(LOCAL_ACTION));
通过 sendBroadcast 函数来发送广播
1
lbm.sendBroadcast(new Intent(LOCAL_ACTION));
以下我们简单来做个Demo,实际体会一下。例子很简单,一个布局文件加一个主Activity。
布局文件
1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/sendLocal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送本地广播" />
</RelativeLayout>
主Activity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private final String ACTION = "org.bridge.localreceiver.LOCAL_BROADCAST";
private LocalBroadcastManager manager;
private LocalReceiver localReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
manager = LocalBroadcastManager.getInstance(this);
//新建intentFilter
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION);
localReceiver = new LocalReceiver();
manager.registerReceiver(localReceiver, filter);
findViewById(R.id.sendLocal).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.sendLocal:
Intent intent = new Intent(ACTION);
manager.sendBroadcast(intent);
// manager.sendBroadcastSync();
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
manager.unregisterReceiver(localReceiver);
}
}
运行结果
点击发送按钮,我们的应用成功收到了广播,接下来我们分析一下,本地广播是如何实现只在当前应用内发送和接受的。
原理分析
以下是LocalBroadcastManager的源代码,整个类代码量不多,还是较为简单的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
public final class LocalBroadcastManager {
//静态内部类,ReceiverRecord 封装了BroadcastReceiver和IntentFilter
private static class ReceiverRecord {
final IntentFilter filter;
final BroadcastReceiver receiver;
boolean broadcasting;
ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver) {
filter = _filter;
receiver = _receiver;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(128);
builder.append("Receiver{");
builder.append(receiver);
builder.append(" filter=");
builder.append(filter);
builder.append("}");
return builder.toString();
}
}
//静态内部类BroadcastRecord ,封装了Intent 和对应的ReceiverRecord
private static class BroadcastRecord {
final Intent intent;
final ArrayList<ReceiverRecord> receivers;
BroadcastRecord(Intent _intent, ArrayList<ReceiverRecord> _receivers) {
intent = _intent;
receivers = _receivers;
}
}
private static final String TAG = "LocalBroadcastManager";
private static final boolean DEBUG = false;
private final Context mAppContext;
//BroadReceiver和对应IntentFilter映射
private final HashMap<BroadcastReceiver, ArrayList<IntentFilter>> mReceivers
= new HashMap<BroadcastReceiver, ArrayList<IntentFilter>>();
private final HashMap<String, ArrayList<ReceiverRecord>> mActions
= new HashMap<String, ArrayList<ReceiverRecord>>();
private final ArrayList<BroadcastRecord> mPendingBroadcasts
= new ArrayList<BroadcastRecord>();
static final int MSG_EXEC_PENDING_BROADCASTS = 1;
private final Handler mHandler;
private static final Object mLock = new Object();
private static LocalBroadcastManager mInstance;
//单例模式获取实例
public static LocalBroadcastManager getInstance(Context context) {
synchronized (mLock) {
if (mInstance == null) {
mInstance = new LocalBroadcastManager(context.getApplicationContext());
}
return mInstance;
}
}
//私有构造方法,构造了一个Handler
private LocalBroadcastManager(Context context) {
mAppContext = context;
mHandler = new Handler(context.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_EXEC_PENDING_BROADCASTS:
executePendingBroadcasts();
break;
default:
super.handleMessage(msg);
}
}
};
}
//注册广播
public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
synchronized (mReceivers) {
ReceiverRecord entry = new ReceiverRecord(filter, receiver);
//从映射表取得receiver对应的IntentFilter
ArrayList<IntentFilter> filters = mReceivers.get(receiver);
//如果没有找到,就添加这个映射
if (filters == null) {
filters = new ArrayList<IntentFilter>(1);
mReceivers.put(receiver, filters);
}
filters.add(filter);
//遍历filter,保存action到mActions中
for (int i=0; i<filter.countActions(); i++) {
String action = filter.getAction(i);
ArrayList<ReceiverRecord> entries = mActions.get(action);
if (entries == null) {
entries = new ArrayList<ReceiverRecord>(1);
mActions.put(action, entries);
}
entries.add(entry);
}
}
}
//注销广播
public void unregisterReceiver(BroadcastReceiver receiver) {
synchronized (mReceivers) {
ArrayList<IntentFilter> filters = mReceivers.remove(receiver);
if (filters == null) {
return;
}
for (int i=0; i<filters.size(); i++) {
IntentFilter filter = filters.get(i);
for (int j=0; j<filter.countActions(); j++) {
String action = filter.getAction(j);
ArrayList<ReceiverRecord> receivers = mActions.get(action);
if (receivers != null) {
for (int k=0; k<receivers.size(); k++) {
if (receivers.get(k).receiver == receiver) {
receivers.remove(k);
k--;
}
}
if (receivers.size() <= 0) {
mActions.remove(action);
}
}
}
}
}
}
//发送广播
public boolean sendBroadcast(Intent intent) {
synchronized (mReceivers) {
final String action = intent.getAction();
final String type = intent.resolveTypeIfNeeded(
mAppContext.getContentResolver());
final Uri data = intent.getData();
final String scheme = intent.getScheme();
final Set<String> categories = intent.getCategories();
final boolean debug = DEBUG ||
((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
if (debug) Log.v(
TAG, "Resolving type " + type + " scheme " + scheme
+ " of intent " + intent);
ArrayList<ReceiverRecord> entries = mActions.get(intent.getAction());
if (entries != null) {
if (debug) Log.v(TAG, "Action list: " + entries);
ArrayList<ReceiverRecord> receivers = null;
for (int i=0; i<entries.size(); i++) {
ReceiverRecord receiver = entries.get(i);
if (debug) Log.v(TAG, "Matching against filter " + receiver.filter);
if (receiver.broadcasting) {
if (debug) {
Log.v(TAG, " Filter's target already added");
}
continue;
}
int match = receiver.filter.match(action, type, scheme, data,
categories, "LocalBroadcastManager");
if (match >= 0) {
if (debug) Log.v(TAG, " Filter matched! match=0x" +
Integer.toHexString(match));
if (receivers == null) {
receivers = new ArrayList<ReceiverRecord>();
}
receivers.add(receiver);
receiver.broadcasting = true;
} else {
if (debug) {
String reason;
switch (match) {
case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;
case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;
case IntentFilter.NO_MATCH_DATA: reason = "data"; break;
case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;
default: reason = "unknown reason"; break;
}
Log.v(TAG, " Filter did not match: " + reason);
}
}
}
if (receivers != null) {
for (int i=0; i<receivers.size(); i++) {
receivers.get(i).broadcasting = false;
}
mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));
if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {
mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);
}
return true;
}
}
}
return false;
}
//发送同步广播
public void sendBroadcastSync(Intent intent) {
if (sendBroadcast(intent)) {
executePendingBroadcasts();
}
}
private void executePendingBroadcasts() {
while (true) {
BroadcastRecord[] brs = null;
synchronized (mReceivers) {
final int N = mPendingBroadcasts.size();
if (N <= 0) {
return;
}
brs = new BroadcastRecord[N];
mPendingBroadcasts.toArray(brs);
mPendingBroadcasts.clear();
}
for (int i=0; i<brs.length; i++) {
BroadcastRecord br = brs[i];
for (int j=0; j<br.receivers.size(); j++) {
br.receivers.get(j).receiver.onReceive(mAppContext, br.intent);
}
}
}
}
}
主要成员变量含义
mReceivers存储广播和过滤器信息,以BroadcastReceiver作为key,IntentFilter链表作为value.mReceivers是接收器和IntentFilter的对应表,主要作用是方便在unregisterReceiver()取消注册,同时作为对象锁限制注册接收器,发送广播,取消接收器注册等几个过程的并发访问。
mActions 以Action为key,注册这个Action的BroadCastReceiver链表为value.mActions的主要作用是方便在广播发送后快速得到可以接受它的BroadCastReceiver.
发送广播的过程
先根据Action从mActions 中取出ReceiverRecord列表,循环每个ReceiverRecord 判断filter和intent 中action,type,scheme,data,categoried 是否match,是的话则保存到receivers列表中,发送what为 MSG_EXEC_PENDING_BROADCASTS的消息,通过Handler处理。
消息处理过程
mPendingBroadcasts转换为数组BroadcastRecord,循环每个receiver,调用其onReceive函数,这样便完成了广播的核心逻辑。
取消注册过程
从mReceivers及mActions中移除相应元素。
总结
LocalBroadcastManager 的核心实现实际上还是Handler,只是利用到了IntentFilter的match功能,至于BroadcastReceiver换成其他接口也无所谓,顺便利用了现成的类和概念而已。
因为采用了Handler实现了应用内通信,自然安全性更好,效率更高。
最后
以上就是落后学姐最近收集整理的关于Android 本地广播LocalBroadcastManager原理分析原理分析的全部内容,更多相关Android内容请搜索靠谱客的其他文章。
发表评论 取消回复