Android LocalBroadcastManager使用方法和代码流程分析 .

来源:互联网 发布:淘宝如何抢秒杀商品 编辑:程序博客网 时间:2024/06/05 08:31
一.   一. LocalBroadcastManager简介
LocalBroadcastManager是AndroidSupport包提供了一个工具,是用来在同一个应用内的不同组件间发送Broadcast的。
注意,这是同一个应用,也就是其他应用就算和你共进程,也是无法互相发送广播的。这点后面源代码流程分析的时候会说明。

使用LocalBroadcastManager有如下好处:
1.       1. 发送的广播只会在自己App内传播,不会泄露给其他App,确保隐私数据不会泄露
2.      2. 其他App也无法向你的App发送该广播,不用担心其他App会来搞破坏
3.      3. 比系统全局广播更加高效

那既然是同一个应用,为啥还要多此一举的使用LocalBroadcast呢,直接调用不可以么?
个人猜测这是Google从设计模式的角度去考虑的问题,使用本地广播可以让代码更好组织,耦合性更低。

二.  二. LocalBroadcastManager使用方法
1.      1. 获取LocalBroadcasetManager实例
LocalBroadcastManager lbm =LocalBroadcastManager.getInstance(this);
2.      注册广播接收器
01lbm.registerReceiver(newBroadcastReceiver() {
02 
03            <a href="http://home.51cto.com/index.php?s=/space/5017954"target="_blank">@override</a>
04 
05            publicvoid onReceive(Context context, Intent intent) {
06 
07                Log.d("Sandy","LocalBroadcastManager onReceive");
08 
09            }
10 
11        },newIntentFilter("com.sandy.localbroadcaset"));
3.      2. 发送广播
1LocalBroadcastManager lb = LocalBroadcastManager.getInstance(MainActivity.this);
2 
3lb.sendBroadcast(newIntent("com.sandy.localbroadcaset"));
这样在之前注册的广播接受方法onReceive就可以接收到发送的本地广播了。

三.  三.  LocalBroadcastManager代码流程分析
1.      1. 获取LocalBroadcastManager实例
1LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
代码:
01privatestatic LocalBroadcastManager mInstance;
02 
03  
04 
05publicstatic LocalBroadcastManager getInstance(Context context) {
06 
07        synchronized(mLock) {
08 
09            if(mInstance == null) {
10 
11            mInstance=newLocalBroadcastManager(context.getApplicationContext());
12 
13            }
14 
15            returnmInstance;
16 
17        }
18 
19}
很明显的一个单例模式,静态的mInstance实例保证变量生命周期和应用程序进程一样。
然后getInstance()方法里面使用同步方法,保证多线程环境下,单例模式不会出现问题。
从这点也可以看出LocalBroadcastManager是一个应用程序内有效,而不是进程内共享。

2.      2. 注册广播接收器
01privatefinal HashMap<BroadcastReceiver, ArrayList<IntentFilter>> mReceivers
02 
03            =newHashMap<BroadcastReceiver, ArrayList<IntentFilter>>();
04 
05privatefinal HashMap<String, ArrayList<ReceiverRecord>> mActions
06 
07            =newHashMap<String, ArrayList<ReceiverRecord>>();
08 
09/**
10 
11     * Register a receive for any local broadcasts that match the given IntentFilter.
12 
13     *
14 
15     * @param receiver The BroadcastReceiver to handle the broadcast.
16 
17     * @param filter Selects the Intent broadcasts to be received.
18 
19     *
20 
21     * @see #unregisterReceiver
22 
23     */
24 
25   publicvoid registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
26 
27        synchronized(mReceivers) {
28 
29            ReceiverRecord entry = newReceiverRecord(filter, receiver);
30 
31            ArrayList<IntentFilter> filters = mReceivers.get(receiver);
32 
33            if(filters == null) {
34 
35                filters = newArrayList<IntentFilter>(1);
36 
37                mReceivers.put(receiver, filters);
38 
39            }
40 
41            filters.add(filter);
42 
43            for(inti=0; i<filter.countActions(); i++) {
44 
45                String action = filter.getAction(i);
46 
47                ArrayList<ReceiverRecord> entries = mActions.get(action);
48 
49                if(entries == null) {
50 
51                    entries = newArrayList<ReceiverRecord>(1);
52 
53                    mActions.put(action, entries);
54 
55                }
56 
57                entries.add(entry);
58 
59            }
60 
61        }
62 
63}
这个方法可以简单的理解为把想要注册的Receiver以及它的IntentFilter保存在mReceivers这个HashMap里面;以及保存在mActions这个HashMap里面。mReceivers和mActions两个HashMap保存的东西是不同的。

3.      3. 发送广播
发送广播分为两种,异步的和同步的;
异步广播的意思是发送广播完毕后,就直接返回,不需要等待广播执行。
那同步广播的意思就是相反,发送广播后,还需要等待广播接收器执行完onReceive方法。
首先看异步广播方法:
01privatefinal HashMap<String, ArrayList<ReceiverRecord>> mActions
02 
03            =newHashMap<String, ArrayList<ReceiverRecord>>();
04 
05         /**
06 
07     * Broadcast the given intent to all interested BroadcastReceivers.  This
08 
09     * call is asynchronous; it returns immediately, and you will continue
10 
11     * executing while the receivers are run.
12 
13     *
14 
15     * @param intent The Intent to broadcast; all receivers matching this
16 
17     *     Intent will receive the broadcast.
18 
19     *
20 
21     * @see #registerReceiver
22 
23     */
24 
25   publicboolean sendBroadcast(Intent intent) {
26 
27        synchronized(mReceivers) {
28 
29            ArrayList<ReceiverRecord> entries = mActions.get(intent.getAction());
30 
31            if(entries != null) {
32 
33                ArrayList<ReceiverRecord> receivers = null;
34 
35                for(inti=0; i<entries.size(); i++) {
36 
37                    ReceiverRecord receiver = entries.get(i);                  
38 
39                    intmatch = receiver.filter.match(action, type, scheme, data,
40 
41                            categories,"LocalBroadcastManager");
42 
43                    if(match >= 0) {
44 
45                        if(receivers == null) {
46 
47                            receivers = newArrayList<ReceiverRecord>();
48 
49                        }
50 
51                        receivers.add(receiver);
52 
53                        receiver.broadcasting = true;
54 
55                    }else{
56 
57                        
58 
59                    }
60 
61                }
62 
63  
64 
65                if(receivers != null) {
66 
67                    for(inti=0; i<receivers.size(); i++) {
68 
69                        receivers.get(i).broadcasting = false;
70 
71                    }
72 
73                    mPendingBroadcasts.add(newBroadcastRecord(intent, receivers));
74 
75                    if(!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {
76 
77                        mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);
78 
79                    }
80 
81                    returntrue;
82 
83                }
84 
85            }
86 
87        }
88 
89        returnfalse;
90 
91   }
这个方法的大概意思就是从mActions里面找到和当前Intent的action匹配的所有注册过的BroadcastReceiver,然后把他们添加到mPendingBroadcasts这个Hashmap里面.
如果receivers != null,也就是找到了匹配的BroadcastReceiver,就发送一个消息MSG_EXEC_PENDING_BROADCASTS --- 执行等待中的Broadcast
代码如下:
01privateLocalBroadcastManager(Context context) {
02 
03        mAppContext = context;
04 
05        mHandler = newHandler(context.getMainLooper()) {
06 
07            <a href="http://home.51cto.com/index.php?s=/space/5017954"target="_blank">@override</a>
08 
09            publicvoid handleMessage(Message msg) {
10 
11                switch(msg.what) {
12 
13                    caseMSG_EXEC_PENDING_BROADCASTS:
14 
15                        executePendingBroadcasts();
16 
17                        break;
18 
19                }
20 
21            }
22 
23        };
24 
25}
26 
27  
28 
29privatevoid executePendingBroadcasts() {
30 
31        while(true) {
32 
33            BroadcastRecord[] brs = null;
34 
35            synchronized(mReceivers) {
36 
37                finalint N = mPendingBroadcasts.size();
38 
39                if(N <= 0) {
40 
41                    return;
42 
43                }
44 
45                brs = newBroadcastRecord[N];
46 
47                mPendingBroadcasts.toArray(brs);
48 
49                mPendingBroadcasts.clear();
50 
51            }
52 
53            for(inti=0; i<brs.length; i++) {
54 
55                BroadcastRecord br = brs[i];
56 
57                for(intj=0; j<br.receivers.size(); j++) {
58 
59                    br.receivers.get(j).receiver.onReceive(mAppContext, br.intent);
60 
61                }
62 
63            }
64 
65        }
66 
67}
逻辑比较简单,不断处理mPendingBroadcasts这个Hashmap里面的BroadcastReceiver,回调BroadcastReceiver的onReceiver()方法,直到mPendingBroadcasts的size为0;

同步广播的话实现方法相对简单,就是同步调用发送广播和回调广播方法,如下:
01/**
02 
03     * Like {@link #sendBroadcast(Intent)}, but if there are any receivers for
04 
05     * the Intent this function will block and immediately dispatch them before
06 
07     * returning.
08 
09     */
10 
11   publicvoid sendBroadcastSync(Intent intent) {
12 
13        if(sendBroadcast(intent)) {
14 
15            executePendingBroadcasts();
16 
17        }
18 
19   }
至此,LocalBroadcastManager的使用方法,以及代码流程分析完毕。 
最后,献上源代码:
 Android.rar (1.37 MB) 
0 0