Android 本地广播 LocalBroadcastManager

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

使用LocalBroadcastManager的好处:
  • 只能传输在App内部,不会被其他App接收,确保数据安全
  • 接收不到其他App广播,免干扰
  • 比BrocastReceiver更加高效

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

private LocalBroadcastManager lm;
private TestReceiver testReceiver;

private void initReceiver() {
    //获取实例
    lm = LocalBroadcastManager.getInstance(this);
    IntentFilter intentFilter = new IntentFilter("com.android.Test");
    testReceiver = new TestReceiver();
    //绑定
    lm.registerReceiver(testReceiver,intentFilter);
}

private class TestReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        String action  = intent.getAction();
        Toast.makeText(MainActivity.this, "action:" + action, Toast.LENGTH_SHORT).show();
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    //解绑
    lm.unregisterReceiver(testReceiver);
}

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

源码

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

@NonNull
public static LocalBroadcastManager getInstance(@NonNull Context context) {
    Object var1 = mLock;
    synchronized(mLock) {
        if (mInstance == null) {
            mInstance = new LocalBroadcastManager(context.getApplicationContext());
        }

        return mInstance;
    }
}

private LocalBroadcastManager(Context context) {
    this.mAppContext = context;
    this.mHandler = new Handler(context.getMainLooper()) {
        public void handleMessage(Message msg) {
            switch(msg.what) {
            case 1:
                LocalBroadcastManager.this.executePendingBroadcasts();
                break;
            default:
                super.handleMessage(msg);
            }

        }
    };
}

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

public void registerReceiver(@NonNull BroadcastReceiver receiver, @NonNull IntentFilter filter) {
    HashMap var3 = this.mReceivers;
    synchronized(this.mReceivers) {
        //构建广播消息体
        LocalBroadcastManager.ReceiverRecord entry = new LocalBroadcastManager.ReceiverRecord(filter, receiver);
        ArrayList<LocalBroadcastManager.ReceiverRecord> filters = (ArrayList)this.mReceivers.get(receiver);
        if (filters == null) {
            filters = new ArrayList(1);
            //添加接收者
            this.mReceivers.put(receiver, filters);
        }

        filters.add(entry);

        for(int i = 0; i < filter.countActions(); ++i) {
            String action = filter.getAction(i);
            ArrayList<LocalBroadcastManager.ReceiverRecord> entries = (ArrayList)this.mActions.get(action);
            if (entries == null) {
                entries = new ArrayList(1);
                //关联广播
                this.mActions.put(action, entries);
            }
            entries.add(entry);
        }
    }
}

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

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

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

void executePendingBroadcasts() {
    while(true) {
        HashMap var2 = this.mReceivers;
        LocalBroadcastManager.BroadcastRecord[] brs;
        synchronized(this.mReceivers) {
            int N = this.mPendingBroadcasts.size();
            if (N <= 0) {
                return;
            }

            brs = new LocalBroadcastManager.BroadcastRecord[N];
            this.mPendingBroadcasts.toArray(brs);
            this.mPendingBroadcasts.clear();
        }
        for(int i = 0; i < brs.length; ++i) {
            LocalBroadcastManager.BroadcastRecord br = brs[i];
            int nbr = br.receivers.size();

            for(int j = 0; j < nbr; ++j) {
                LocalBroadcastManager.ReceiverRecord rec = (LocalBroadcastManager.ReceiverRecord)br.receivers.get(j);
                if (!rec.dead) {
                    rec.receiver.onReceive(this.mAppContext, br.intent);
                }
            }
        }
    }
}

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

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

开车完毕,Over!!!

福利1 免费直播课程

《腾讯课堂Android高级开发工程师系列直播》

适听人群:Android初、中、高级开发工程师

每晚8点准时直播,持续进行

福利2 Android开发资料(部分截图)

《Android 本地广播 LocalBroadcastManager》

想要参与Android进阶免费系列直播课

以及获取Android开发工程师资料包的同学,

点击加入:点击链接加入群聊【Android开发交流】:https://jq.qq.com/?_wv=1027&k=5richpI

免费课程,名额有限,先到先得~~

    原文作者:Android架构木木
    原文地址: https://www.jianshu.com/p/e3b966a2e235
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞