文章目录

        • LocalBroadcastManager 简介
        • LocalBroadcastManager使用
        • LocalBroadcastManager 源码分析

LocalBroadcastManager 简介

学习Android的同鞋一定知道四大组件,四大组件有:
Android本地广播LocalBroadcastManager使用_第1张图片
四大组件中的BroadcastReceiver是全局广播,即发送广播时可能被多个App接收到,有时候从安全角度考虑,为了数据的安全传递,是不是有办法避免被多个App接收广播,于是有了本地广播,本地广播只会在自己的App内传播,用于在同一个应用内的不同组件间发送Broadcast进行通信。使用本地广播,需要用到support库中的LocalBroadcastManager。

LocalBroadcastManager使用

这里先列出LocalBroadcastManager中常用的方法:

LocalBroadcastManager中方法 说明
getInstance(Context context) 获取本地广播实例
registerReceiver(BroadcastReceiver receiver, IntentFilter filter) 注册广播
unregisterReceiver(BroadcastReceiver receiver) 解注册
sendBroadcast(Intent intent) 发送广播(内部使用Handler,保证onReceive在主线程中调用)
sendBroadcastSync(Intent intent) 同步发送广播,如果消息队列中消息太多,会导致广播接收者接收广播太慢,可使用这个方法同步发送广播
  • 获取LocalBroadcastManager对象
    LocalBroadcastManager被设计为一个单例类,通过getInstance方法获取实例,参数需要一个上下文对象
// javaLocalBroadcastManager localManager= LocalBroadcastManager.getInstance(mContext);
// kotlinval localManager = LocalBroadcastManager.getInstance(mContext)
  • 注册观察者
    和全局广播的思想一样,如果要接收广播,那么需要先注册一个广播,才能接收到匹配的广播。本地广播不能通过在AndroidManifest文件中静态声明注册,只能通过动态注册的方法注册,这里注册时需要调用registerReceiver方法,需要传递两个参数BroadcastReceiverIntentFilter
//javaLocalBroadcastManager localManager = LocalBroadcastManager.getInstance(mContext);BroadcastReceiver receiver = new BroadcastReceiver() {    @Override    public void onReceive(Context context, Intent intent) {        Toast.makeText(context, "收到广播", Toast.LENGTH_SHORT).show();    }};IntentFilter intentFilter = new IntentFilter("LocalBroadcastManager-test");localManager.registerReceiver(receiver, intentFilter);//注册广播
//kotlinval localManager = LocalBroadcastManager.getInstance(mContext)val broadReceiver = object : BroadcastReceiver() {    override fun onReceive(context: Context?, intent: Intent?) {        Toast.makeText(context, "收到广播", Toast.LENGTH_SHORT).show()    }}val intentFilter = IntentFilter("LocalBroadcastManager-test")localManager.registerReceiver(broadReceiver, intentFilter)
  • 通过本地发送广播
    通过上面定义BroadcastReceiver来接收广播处理,现在可以发送广播试试了
//javalocalManager.sendBroadcast(new Intent("LocalBroadcastManager-test"));
//kotlinlocalManager.sendBroadcast(Intent("LocalBroadcastManager-test"))

Android本地广播LocalBroadcastManager使用_第2张图片

LocalBroadcastManager 源码分析

LocalBroadcastManager位于android.support.v4.content包下

因为本地广播基于观察者模式设计,所以将LocalBroadcastManager设计成单例,被观察者只有一个嘛,以下是获取实例和私有构造方法

// 忽略部分代码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;    //UI线程的Looper,说明可以在子线程获取实例、发送广播    this.mHandler = new Handler(context.getMainLooper()) {        public void handleMessage(Message msg) {            switch(msg.what) {            case 1:                LocalBroadcastManager.this.executePendingBroadcasts();                break;            default:                super.handleMessage(msg);            }        }    };}

在LocalBroadcastManager中有两个内部静态类,封装了BroadcastReceiver和IntentFilter

// 忽略部分代码private static final class ReceiverRecord {    final IntentFilter filter;//注册广播时的intentFilter    final BroadcastReceiver receiver;//注册广播时的broadcastReceiver    boolean broadcasting;//是否添加到广播队列    boolean dead;//死亡标识     ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver) {        this.filter = _filter;        this.receiver = _receiver;    }    public String toString() {        StringBuilder builder = new StringBuilder(128);        builder.append("Receiver{");        builder.append(this.receiver);        builder.append(" filter=");        builder.append(this.filter);        if (this.dead) {            builder.append(" DEAD");        }        builder.append("}");        return builder.toString();    }}private static final class BroadcastRecord {    final Intent intent;//发送广播的intent    final ArrayList<LocalBroadcastManager.ReceiverRecord> receivers;//发送广播intent匹配的receivers    BroadcastRecord(Intent _intent, ArrayList<LocalBroadcastManager.ReceiverRecord> _receivers) {        this.intent = _intent;        this.receivers = _receivers;    }}

下面看下注册观察都和解注册的代码

// 保存所有注册BroadcastReceiver的HashMapprivate final HashMap<BroadcastReceiver, ArrayList<LocalBroadcastManager.ReceiverRecord>> mReceivers = new HashMap();//保存所有注册BroadcastReceiver中IntentFilter的actionprivate final HashMap<String, ArrayList<LocalBroadcastManager.ReceiverRecord>> mActions = new HashMap();public void registerReceiver(@NonNull BroadcastReceiver receiver, @NonNull IntentFilter filter) {    HashMap var3 = this.mReceivers;    synchronized(this.mReceivers) {       // 创建一个LocalBroadcastManager.ReceiverRecord对象        LocalBroadcastManager.ReceiverRecord entry = new LocalBroadcastManager.ReceiverRecord(filter, receiver);        // 从mReceivers中获取是否存在的LocalBroadcastManager.ReceiverRecord对象        ArrayList<LocalBroadcastManager.ReceiverRecord> filters = (ArrayList)this.mReceivers.get(receiver);        if (filters == null) {           //如果mReceivers不存在要注册的receiver,则创建一个新的,保存到Mreceivers中            filters = new ArrayList(1);            this.mReceivers.put(receiver, filters);//保存receiver对应的LocalBroadcastManager.ReceiverRecord        }        filters.add(entry);        for(int i = 0; i < filter.countActions(); ++i) {            // 遍历获取filter中所有的action,保存到mActions中            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);//保存action对应的LocalBroadcastManager.ReceiverRecord            }            entries.add(entry);        }    }}public void unregisterReceiver(@NonNull BroadcastReceiver receiver) {    HashMap var2 = this.mReceivers;    synchronized(this.mReceivers) {       //mReceivers中移除已注册的receiver        ArrayList<LocalBroadcastManager.ReceiverRecord> filters = (ArrayList)this.mReceivers.remove(receiver);        if (filters != null) {//移除成功不为null            for(int i = filters.size() - 1; i >= 0; --i) {                LocalBroadcastManager.ReceiverRecord filter = (LocalBroadcastManager.ReceiverRecord)filters.get(i);                filter.dead = true;//死亡标识                for(int j = 0; j < filter.filter.countActions(); ++j) {                    String action = filter.filter.getAction(j);                    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);                            if (rec.receiver == receiver) {                                rec.dead = true;//标识死亡                                receivers.remove(k);//先移除mAction中action对应List中的                            }                        }                        if (receivers.size() <= 0) {                            this.mActions.remove(action);//如果action对应的list为0,移除mAction中的action                        }                    }                }            }        }    }}

发送广播的逻辑

public boolean sendBroadcast(@NonNull Intent intent) {    HashMap var2 = this.mReceivers;    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;        if (debug) {            Log.v("LocalBroadcastManager", "Resolving type " + type + " scheme " + scheme + " of intent " + intent);        }// 获取匹配的action的ReceiverRecord对象        ArrayList<LocalBroadcastManager.ReceiverRecord> entries = (ArrayList)this.mActions.get(intent.getAction());        if (entries != null) {            if (debug) {                Log.v("LocalBroadcastManager", "Action list: " + entries);            }            ArrayList<LocalBroadcastManager.ReceiverRecord> receivers = null;            int i;            //遍历匹配到action的广播            for(i = 0; i < entries.size(); ++i) {                LocalBroadcastManager.ReceiverRecord receiver = (LocalBroadcastManager.ReceiverRecord)entries.get(i);                if (debug) {                    Log.v("LocalBroadcastManager", "Matching against filter " + receiver.filter);                }                if (receiver.broadcasting) {                    if (debug) {                        Log.v("LocalBroadcastManager", "  Filter's target already added");                    }                } else {                    int match = receiver.filter.match(action, type, scheme, data, categories, "LocalBroadcastManager");                    if (match >= 0) {                        if (debug) {                            Log.v("LocalBroadcastManager", "  Filter matched!  match=0x" + Integer.toHexString(match));                        }                        if (receivers == null) {                            receivers = new ArrayList();                        }                        receivers.add(receiver);                        receiver.broadcasting = true;                    } else if (debug) {                        String reason;                        switch(match) {                        case -4:                            reason = "category";                            break;                        case -3:                            reason = "action";                            break;                        case -2:                            reason = "data";                            break;                        case -1:                            reason = "type";                            break;                        default:                            reason = "unknown reason";                        }                        Log.v("LocalBroadcastManager", "  Filter did not match: " + reason);                    }                }            }            if (receivers != null) {                for(i = 0; i < receivers.size(); ++i) {                    ((LocalBroadcastManager.ReceiverRecord)receivers.get(i)).broadcasting = false;                }// 添加到广播队列                this.mPendingBroadcasts.add(new LocalBroadcastManager.BroadcastRecord(intent, receivers));                if (!this.mHandler.hasMessages(1)) {                  //发送消息                    this.mHandler.sendEmptyMessage(1);                }                return true;            }        }        return false;    }}

sendBroadcastSync方法有些不同,可自行查看源码
下面来看下处理广播的逻辑

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); //转换array            this.mPendingBroadcasts.clear();//清空操作        }        for(int i = 0; i < brs.length; ++i) {            LocalBroadcastManager.BroadcastRecord br = brs[i];            int nbr = br.receivers.size();       // 遍历回调onReceiver方法            for(int j = 0; j < nbr; ++j) {                LocalBroadcastManager.ReceiverRecord rec = (LocalBroadcastManager.ReceiverRecord)br.receivers.get(j);                if (!rec.dead) {//如果没有dead调用onReceiver方法                    rec.receiver.onReceive(this.mAppContext, br.intent);                }            }        }    }}

到这里就把整个逻辑分析了,主要逻辑有:

  • 在LocalBroadcastManager中通过registerReceiver中注册广播,保存到mReceiversmActions
  • 通过sendBroadcast中匹配mActions中的BroadcastReceiver,将匹配到的对象保存到mPendingBroadcasts
  • 最终调用executePendingBroadcasts来发送广播

更多相关文章

  1. Android读取文件方法总结
  2. Android中Intent传递对象的两种方法(Serializable,Parcelable)!
  3. Mac安装android studio后卡在building gradle project info的解
  4. appium 【已解决】Android,每次启动手机中都会安装Appium setting
  5. android 图片压缩的几种方法
  6. Android SqLite中insert()方法解析
  7. android设备调用usb外置摄像头方法及案例
  8. Android基础教程之-------Android中两种设置全屏的方法!!!

随机推荐

  1. Android——Toast.makeText()
  2. Android(安卓)NDK生成共享库和静态库
  3. Android(安卓)AsyncTask基础知识整理
  4. android中的launcher介绍
  5. Android(安卓)录制mp3使用mp3lame 库
  6. android客户端访问服务端tomcat
  7. ToolBar随ScrollView的滚动改变透明度
  8. android wifi讲解 wifi列表显示
  9. 导入一个android项目报错的解决办法
  10. Android系统移植与调试之------->如何修