Android 本地广播 LocalBroadcastManager源码解析

参考资料:

介绍
  1. 发送本地广播只会在自己APP里传播
  2. 其他APP发送的广播无法接收到
  3. 比全局广播效率高
使用

本地广播只能动态注册,无法像全局广播那样可以注册到manifest文件中, 它不允许接授从外部发来的广播.

  1. 获取单例实体
LocalBroadcastManager l bm = LocalBroadcastManager.geti nstance(this); 
  1. 注册,这个与本地广播一样
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
    }
};
lbm.registerReceiver(broadcastReceiver,new IntentFilter("LOCA_ACCTION"));
  1. 解绑
lbm.unregisterReceiver(broadcastReceiver);
  1. 发送广播
lbm.sendBroadcast(new Intent("LOCA_ACCTION"));
源码解析 LocalBroadcastManager
  1. 变量
//每个广播接收者对应一个接收记录者集合
private final HashMap<BroadcastReceiver, ArrayList<LocalBroadcastManager.ReceiverRecord>> mReceivers = new HashMap();
//每个`action` 对应一个接收记录者记录集合
private final HashMap<String, ArayList<LocalBroadcastManager.ReceiverRecord>> mActions = new HashMap();
//这个集合专门记录广播记录者,它里面有一个表变量,专门用来记录接收记录着集合.
private final ArrayList<LocalBroadcastManager.BroadcastRecord> mPendingBroadcasts = new ArrayList();
  1. 注册
public void registerReceiver(@NonNull BroadcastReceiver receiver, @NonNull IntentFilter filter) {
        synchronized(this.mReceivers) {
             //按照BroadcastReceiver这个维度来记录的.
  
            //创建一个接收记录者对象,该对象中包含过滤规则和广播接收者.
            LocalBroadcastManager.ReceiverRecord entry = new LocalBroadcastManager.ReceiverRecord(filter, receiver);
            //通过广播接收者获取接收记录者集合.
            ArrayList<LocalBroadcastManager.ReceiverRecord> filters = (ArrayList)this.mReceivers.get(receiver);
            if (filters == null) {
                //如果接收记录者的集合为空, 那么广播接收者还未存在与mReceivers Map集合中.
                filters = new ArrayList(1);
                //就将广播接收者与接收记录者集合存入mReceivers Map集合中.
                this.mReceivers.put(receiver, filters);
            }
            //将新的接收记录者对象存入广播接收者对应的接收记录者Map集合中.
            filters.add(entry);

            //按照action这个维度来记录的.
            for(int i = 0; i < filter.countActions(); ++i) {
                //获取将要注册的过滤规则`action`
                String action = filter.getAction(i);
                //从`action`中取出对应的接收记录者集合
                ArrayList<LocalBroadcastManager.ReceiverRecord> entries = (ArrayList)this.mActions.get(action);
                if (entries == null) {
                    //如果该集合为空,就新建一个`action`对应的接收记录者集合
                    entries = new ArrayList(1);
                    //将`action`与接收记录者集合存入mActions Map中
                    this.mActions.put(action, entries);
                }
                //这一步是将新的接收记录者对象存入`action`对应的接收记录者Map集合中.
                entries.add(entry);
            }

        }
    }
  1. 取消注册
public void unregisterReceiver(@NonNull BroadcastReceiver receiver) {
    synchronized(this.mReceivers) {
        //这里从BroadcastReceiver这个维度删除记录.

        //待取消的广播接收者知道后可以从mReceivers Map集合中得到接收记录者集合.
        ArrayList<LocalBroadcastManager.ReceiverRecord> filters = (ArrayList)this.mReceivers.remove(receiver);
        
        //按照action维度来删除记录
        if (filters != null) {
            //如果这个待取消广播接收者对应的接收记录者集合不为空,对该集合进行遍历.
            for(int i = filters.size() - 1; i >= 0; --i) {
                //取出每一个接收记录者对象,并且标记为死亡.
                LocalBroadcastManager.ReceiverRecord filter = (LocalBroadcastManager.ReceiverRecord)filters.get(i);
                filter.dead = true;
                //对每一个接收记录者之中的IntentFilter对象中的`action`值进行遍历,
                for(int j = 0; j < filter.filter.countActions(); ++j) {
                    String action = filter.filter.getAction(j);
                    //根据action,从mActions Map集合中取出接收记录者对象集合.
                    ArrayList<LocalBroadcastManager.ReceiverRecord> receivers = (ArrayList)this.mActions.get(action);
                    if (receivers != null) {
                        for(int k = receivers.size() - 1; k >= 0; --k) {
                            //遍历接收记录者对象集合,取出每一个接收记录者对象
                            LocalBroadcastManager.ReceiverRecord rec = (LocalBroadcastManager.ReceiverRecord)receivers.get(k);
                            //如果每个接收记录者对象中的广播接收者与传入的待取消的广播接收者对象相同,那么就从mActions Map集合中对应的接收记录者集合中删除该广播接收者.
                            if (rec.receiver == receiver) {
                                rec.dead = true;
                                receivers.remove(k);
                            }
                        }
                        if (receivers.size() <= 0) {
                            //如果该接收记录者集合长度为0.就从mActions Map中删除这个集合.
                            this.mActions.remove(action);
                        }
                    }
                }
            }
        }
    }
}
  1. 发送消息
//第一步
public boolean sendBroadcast(@NonNull Intent intent) {
    synchronized(this.mReceivers) {
        String action = intent.getAction();
        String type = intent.resolveTypeIfNeeded(this.mAppContext.getContentResolver());
        Uri data = intent.getData();
        String scheme = intent.getScheme();
        Set<String> categories = intent.getCategories();
        boolean debug = (intent.getFlags() & 8) != 0;
        //通过传入的intent获取action,再从mActions Map中得到接收记录者集合.
        ArrayList<LocalBroadcastManager.ReceiverRecord> entries = (ArrayList)this.mActions.get(intent.getAction());
        if (entries != null) {
            ArrayList<LocalBroadcastManager.ReceiverRecord> receivers = null;
            int i;
            //通过接收记录者集合,遍历其中的对象
            for(i = 0; i < entries.size(); ++i) {
                LocalBroadcastManager.ReceiverRecord receiver = (LocalBroadcastManager.ReceiverRecord)entries.get(i);
                if (receiver.broadcasting) {
                    //如果是已经在接收广播的接收记录者对象, 那么就什么都不处理
                } else {
                    //如果该对象不是处于接收记录广播状态中,那么执行下面的逻辑.
                    //首先是看传入的intent中的设置与接收记录者中的IntentFilter设置相匹配不, 匹配的话,match将>=0.
                    int match = receiver.filter.match(action, type, scheme, data, categories, "LocalBroadcastManager");
                    if (match >= 0) {
                        if (receivers == null) {
                            //这个集合是专门用来存储正在接收广播的接收记录者的.
                            receivers = new ArrayList();
                        }
                        //将符合条件的接收记录者放入receivers集合中.
                        receivers.add(receiver);
                        //将该接收记录者中标记为正在接收广播中
                        receiver.broadcasting = true;
                    } else if (debug) {
                        //这里是不匹配, 源码中在这里打印了一些日志记录
                    }
                }
            }
            //对正在接收广播的接收记录者集合进行处理.
            if (receivers != null) {
                for(i = 0; i < receivers.size(); ++i) {
                    //将集合中所有的正在接收广播的标记置为false, 现在就是不接收.
                    ((LocalBroadcastManager.ReceiverRecord)receivers.get(i)).broadcasting = false;
                }
                //使用上面的接收记录者集合和传入的Intent消息对象创建一个广播记录者,
                //并将广播记录者对象传入mPendingBroadcasts集合中去.
                this.mPendingBroadcasts.add(new LocalBroadcastManager.BroadcastRecord(intent, receivers));
                //hasMessages 检查消息队列中是否有what=1的待处理消息,如果没有,就开始发送消息.
                if (!this.mHandler.hasMessages(1)) {
                    //再往下看需要去看看mHandler对象的handleMessage方法了.看第二步.
                    this.mHandler.sendEmptyMessage(1);
                }
                return true;
            }
        }
        return false;
    }
}
//第二步
private LocalBroadcastManager(Context context) {
    this.mAppContext = context;//这里其实是一个applicationContext
    this.mHandler = new Handler(context.getMainLooper()) {
        public void handleMessage(Message msg) {
            switch(msg.what) {
            case 1:
                //executePendingBroadcasts() 该方法是真正的发送消息了
                LocalBroadcastManager.this.executePendingBroadcasts();
                break;
            default:
                super.handleMessage(msg);
            }
        }
    };
}
//第三步
void executePendingBroadcasts() {
    while(true) {
        LocalBroadcastManager.BroadcastRecord[] brs;
        synchronized(this.mReceivers) {
            //mPendingBroadcasts集合中记录的其实是正在等待接收广播的广播记录者,
            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) {
                    //判断接收记录者对象是否死亡,如果还活着,
                    //取出接收记录者对象中的广播接收者回调onReceive方法.至此从注册到回调到注销完成.
                    rec.receiver.onReceive(this.mAppContext, br.intent);
                }
            }
        }
    }
}

你可能感兴趣的:(#,Android,Framwork,Android)