Android 本地广播 LocalBroadcastManager

LocalBroadcastManager 相信有不少人会有点认生,他是android.support.v4中的一个类,本地广播,只在App内部传播,大家熟知的广播,BrocastReceiver是全局广播,可以跨进程通信,而LocalBroadcastManager,只是作为一个本地消息和数据传输的手段,当然,还是有不少人再用EventBus这类的消息事件库,不过我不喜欢用第三方的库,虽然EventBus也比较小,之前一直在使用BrocastReceiver,也比较随意,后来接触的项目多了,很多事情就需要考虑到了。

使用LocalBroadcastManager的好处:

  • 1.只能传输在App内部,不会被其他App接收,确保数据安全

  • 2.接收不到其他App广播,免干扰

  • 3.比BrocastReceiver更加高效

不过要注意的是,LocalBroadcastManager不能静态注册,只能动态注册,这一特性也反应了第二点,不需要接收其他App的广播,那么我们来看下如何使用吧:

 1private LocalBroadcastManager lm;
2private TestReceiver testReceiver;
3
4private void initReceiver() {
5    //获取实例
6    lm = LocalBroadcastManager.getInstance(this);
7    IntentFilter intentFilter = new IntentFilter("com.android.Test");
8    testReceiver = new TestReceiver();
9    //绑定
10    lm.registerReceiver(testReceiver,intentFilter);
11}
12
13private class TestReceiver extends BroadcastReceiver{
14
15    @Override
16    public void onReceive(Context context, Intent intent) {
17        String action  = intent.getAction();
18        Toast.makeText(MainActivity.this"action:" + action, Toast.LENGTH_SHORT).show();
19    }
20}
21
22@Override
23protected void onDestroy() {
24    super.onDestroy();
25    //解绑
26    lm.unregisterReceiver(testReceiver);
27}

使用的方式和BrocastReceiver也差不多,但是要注意的就是,我们用过LocalBroadcastManager.getInstance获取实例后,注册,解绑和发送都需要这个实例才可以

源码

我们来看下LocalBroadcastManager的源码是如何工作的,其实他的源码也没有多少,他获取是通过单例来实现的

 1@NonNull
2public static LocalBroadcastManager getInstance(@NonNull Context context) {
3    Object var1 = mLock;
4    synchronized(mLock) {
5        if (mInstance == null) {
6            mInstance = new LocalBroadcastManager(context.getApplicationContext());
7        }
8
9        return mInstance;
10    }
11}
12
13private LocalBroadcastManager(Context context) {
14    this.mAppContext = context;
15    this.mHandler = new Handler(context.getMainLooper()) {
16        public void handleMessage(Message msg) {
17            switch(msg.what) {
18            case 1:
19                LocalBroadcastManager.this.executePendingBroadcasts();
20                break;
21            default:
22                super.handleMessage(msg);
23            }
24
25        }
26    };
27}

单例后,在构造函数里初始化了一个Handler,这个Handler我们等下将,接着我们先来看下他的注册:

 1public void registerReceiver(@NonNull BroadcastReceiver receiver, @NonNull IntentFilter filter{
2    HashMap var3 = this.mReceivers;
3    synchronized(this.mReceivers) {
4        //构建广播消息体
5        LocalBroadcastManager.ReceiverRecord entry = new LocalBroadcastManager.ReceiverRecord(filter, receiver);
6        ArrayList filters = (ArrayList)this.mReceivers.get(receiver);
7        if (filters == null) {
8            filters = new ArrayList(1);
9              //添加接收者
10            this.mReceivers.put(receiver, filters);
11        }
12
13        filters.add(entry);
14
15        for(int i = 0; i < filter.countActions(); ++i) {
16            String action = filter.getAction(i);
17            ArrayList entries = (ArrayList)this.mActions.get(action);
18            if (entries == null) {
19                entries = new ArrayList(1);
20                //关联广播
21                this.mActions.put(action, entries);
22            }
23            entries.add(entry);
24        }
25    }
26}

注册的时候,他先构建了一个广播信息体ReceiverRecord,并且将我们注册传入的信息添加到Receiver,然后遍历Action,并且关联Action和事件,然后调用sendBroadcast去发送广播,他对数据做了处理之后,开始分类,也就有了我们的Bundler,Data之类的数据了,其实最后调用的代码:

1this.mPendingBroadcasts.add(new LocalBroadcastManager.BroadcastRecord(intent, receivers));
2if (!this.mHandler.hasMessages(1)) {
3    this.mHandler.sendEmptyMessage(1);
4}

就是这一段,这一段也很简单,将广播加入mPendingBroadcasts后发送一个What为1的Handler,而这个Handler就是之前获取单例后他在构造方法里创建的,所以你看这个what=1的判断里,他最终执行的函数为executePendingBroadcasts,代码不多,可以贴出来:

 1void executePendingBroadcasts() {
2    while(true) {
3        HashMap var2 = this.mReceivers;
4        LocalBroadcastManager.BroadcastRecord[] brs;
5        synchronized(this.mReceivers) {
6            int N = this.mPendingBroadcasts.size();
7            if (N <= 0) {
8                return;
9            }
10
11            brs = new LocalBroadcastManager.BroadcastRecord[N];
12            this.mPendingBroadcasts.toArray(brs);
13            this.mPendingBroadcasts.clear();
14        }
15        for(int i = 0; i < brs.length; ++i) {
16            LocalBroadcastManager.BroadcastRecord br = brs[i];
17            int nbr = br.receivers.size();
18
19            for(int j = 0; j < nbr; ++j) {
20                LocalBroadcastManager.ReceiverRecord rec = (LocalBroadcastManager.ReceiverRecord)br.receivers.get(j);
21                if (!rec.dead) {
22                    rec.receiver.onReceive(this.mAppContext, br.intent);
23                }
24            }
25        }
26    }
27}

我们可以通过这个双层for循环看到他最终是取得了监听的广播消息体brs里的数据,得到一个BroadcastRecord,然后调用br.receivers.get获取到接收对象rec,再通过rec.receiver.onReceive通知监听着,实现了消息的发送和接收

整个设计理念就是观察者模式了,对象一对多的关系依赖,当一个对象发生改变的时候,他的所有依赖者都将受到通知并且自动更新。

开车完毕,Over!!!


征稿科技互联网,技术类文章

投稿方式:

发送文章链接地址到邮箱:[email protected]

注明“投稿”,收到会回复哟

你可能感兴趣的:(Android 本地广播 LocalBroadcastManager)