LocalBroadcastManager分析

在Android系统中,BroadcastReceiver的设计初衷就是从全局考虑的,能够方便应用程序和系统、应用程序之间、应用程序内的通讯,因此对单个应用程序而言BroadcastReceiver是存在安全性问题的,相应问题及解决以下:html

一、当应用程序发送某个广播时系统会将发送的Intent与系统中全部注册的BroadcastReceiver的IntentFilter进行匹配,若匹配成功则执行相应的onReceive函数。能够经过相似sendBroadcast(Intent, String)的接口在发送广播时指定接收者必须具有的permission。或经过Intent.setPackage设置广播仅对某个程序有效。java

二、当应用程序注册了某个广播时,即使设置了IntentFilter仍是会接收到来自其余应用程序的广播进行匹配判断。对于动态注册的广播能够经过相似registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)的接口指定发送者必须具有的permission,对于静态注册的广播能够经过android:exported="false"属性表示接收者对外部应用程序不可用,即不接受来自外部的广播。android

LocalBroadcastManager是Android Support包提供了一个工具,是用来在同一个应用内的不一样组件间发送Broadcast的。数组

使用LocalBroadcastManager有以下好处:安全

  • 发送的广播只会在本身App内传播,不会泄露给其余App,确保隐私数据不会泄露
  • 其余App也没法向你的App发送该广播,不用担忧其余App会来搞破坏
  • 比系统全局广播BroadcastReceiver更加高效

LocalBroadcastManager 的使用跟通常 BroadcastReceiver 差异不大。并发

三、实现

(1) 构造函数ide

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

private LocalBroadcastManager(Context context) {
    mAppContext = context;
    mHandler = new Handler(context.getMainLooper()) {

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_EXEC_PENDING_BROADCASTS:
                    executePendingBroadcasts();
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    };
}

注意的是基于主线程的 Looper 新建了一个 Handler,handleMessage中会调用接收器对广播的消息进行处理,也是 LocalBroadcastManager 的核心部分,具体见后面executePendingBroadcasts()介绍。函数

(2) 注册接收器工具

HashMap<BroadcastReceiver, ArrayList<IntentFilter>> mReceivers
            = new HashMap<BroadcastReceiver, ArrayList<IntentFilter>>();
HashMap<String, ArrayList<ReceiverRecord>> mActions
            = new HashMap<String, ArrayList<ReceiverRecord>>();

public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
    synchronized (mReceivers) {
        ReceiverRecord entry = new ReceiverRecord(filter, receiver);
        ArrayList<IntentFilter> filters = mReceivers.get(receiver);
        if (filters == null) {
            filters = new ArrayList<IntentFilter>(1);
            mReceivers.put(receiver, filters);
        }
        filters.add(filter);
        for (int i=0; i<filter.countActions(); i++) {
            String action = filter.getAction(i);
            ArrayList<ReceiverRecord> entries = mActions.get(action);
            if (entries == null) {
                entries = new ArrayList<ReceiverRecord>(1);
                mActions.put(action, entries);
            }
            entries.add(entry);
        }
    }
}

mReceivers 存储广播和过滤器信息,以BroadcastReceiver做为 key,IntentFilter链表做为 value。
mReceivers 是接收器和IntentFilter的对应表,主要做用是方便在unregisterReceiver(…)取消注册,同时做为对象锁限制注册接收器、发送广播、取消接收器注册等几个过程的并发访问。oop

mActions 以Action为 key,注册这个ActionBroadcastReceiver链表为 value。mActions 的主要做用是方便在广播发送后快速获得能够接收它的BroadcastReceiver

(3) 发送广播

public boolean sendBroadcast(Intent intent) {
    synchronized (mReceivers) {
        final String action = intent.getAction();
        final String type = intent.resolveTypeIfNeeded(mAppContext.getContentResolver());
        final Uri data = intent.getData();
        final String scheme = intent.getScheme();
        final Set<String> categories = intent.getCategories();
        ……
        ArrayList<ReceiverRecord> entries = mActions.get(intent.getAction());
        if (entries != null) {
            if (debug) Log.v(TAG, "Action list: " + entries);

            ArrayList<ReceiverRecord> receivers = null;
            for (int i=0; i<entries.size(); i++) {
                ReceiverRecord receiver = entries.get(i);
                if (receiver.broadcasting) {
                    if (debug) {
                        Log.v(TAG, "  Filter's target already added");
                    }
                    continue;
                }

                int match = receiver.filter.match(action, type, scheme, data,
                        categories, "LocalBroadcastManager");
                if (match >= 0) {
                    if (debug) Log.v(TAG, "  Filter matched!  match=0x" +
                            Integer.toHexString(match));
                    if (receivers == null) {
                        receivers = new ArrayList<ReceiverRecord>();
                    }
                    receivers.add(receiver);
                    receiver.broadcasting = true;
                } else {
                    ……
                }
            }

            if (receivers != null) {
                for (int i=0; i<receivers.size(); i++) {
                    receivers.get(i).broadcasting = false;
                }
                mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));
                if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {
                    mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);
                }
                return true;
            }
        }
    }
    return false;
}

先根据ActionmActions中取出ReceiverRecord列表,循环每一个ReceiverRecord判断 filter 和 intent 中的 action、type、scheme、data、categoried 是否 match,是的话则保存到receivers列表中,发送 what 为MSG_EXEC_PENDING_BROADCASTS的消息,经过 Handler 去处理。

(4) 消息处理

private void executePendingBroadcasts() {
    while (true) {
        BroadcastRecord[] brs = null;
        synchronized (mReceivers) {
            final int N = mPendingBroadcasts.size();
            if (N <= 0) {
                return;
            }
            brs = new BroadcastRecord[N];
            mPendingBroadcasts.toArray(brs);
            mPendingBroadcasts.clear();
        }
        for (int i=0; i<brs.length; i++) {
            BroadcastRecord br = brs[i];
            for (int j=0; j<br.receivers.size(); j++) {
                br.receivers.get(j).receiver.onReceive(mAppContext, br.intent);
            }
        }
    }
}

mPendingBroadcasts转换为数组BroadcastRecord,循环每一个receiver,调用其onReceive函数,这样便完成了广播的核心逻辑。

(5) 取消注册

public void unregisterReceiver(BroadcastReceiver receiver) {
    synchronized (mReceivers) {
        ArrayList<IntentFilter> filters = mReceivers.remove(receiver);
        if (filters == null) {
            return;
        }
        for (int i=0; i<filters.size(); i++) {
            IntentFilter filter = filters.get(i);
            for (int j=0; j<filter.countActions(); j++) {
                String action = filter.getAction(j);
                ArrayList<ReceiverRecord> receivers = mActions.get(action);
                if (receivers != null) {
                    for (int k=0; k<receivers.size(); k++) {
                        if (receivers.get(k).receiver == receiver) {
                            receivers.remove(k);
                            k--;
                        }
                    }
                    if (receivers.size() <= 0) {
                        mActions.remove(action);
                    }
                }
            }
        }
    }
}

到此为止咱们便很是清晰了:
(1) LocalBroadcastManager 的核心实现实际仍是 Handler,只是利用到了 IntentFilter 的 match 功能,至于 BroadcastReceiver 换成其余接口也无所谓,顺便利用了现成的类和概念而已。
(2) 由于是 Handler 实现的应用内的通讯,天然安全性更好,效率更高。

(3) 原理其实很简单,就是register时,将要执行的Broadcast保存起来,sendBroadcast时,遍历执行,之因此使用Handler,是由于要保证onReceive方法的执行时在主线程。建立一个使用MainLooper的Handler,这样,即便sendBroadcast方法是在子线程,经过Handler后,仍是在主线程执行的onReceive方法。

相关文章
相关标签/搜索