LocalBroadcastManager用法

来源:互联网 发布:淘宝店封了怎么办 编辑:程序博客网 时间:2024/06/06 12:20

在Android系统中,Broadcast是一种在程序中广泛应用的机制,其作用主要是在程序内或程序间传递消息,基本原理是广播监听者注册监听感兴趣的广播,收到广播后进行自身逻辑的处理。
Android系统提供的基本组件是BroadcastReceiver,其设计初衷是从全局考虑,可以方便应用程序和系统、应用程序之间、应用程序内的通信,所以对单个应用程序而言 这种方式存在安全隐患 (恶意程序脚本不断的去发送你监听的广播)。LocalBroadcastManager的产生,很好的解决了这个隐患。

LocalBroadcastManager

LocalBroadcastManager存在于Android Support包中,用于在同一个应用内的不同组件间发送Broadcast,也被称为局部通知管理器,它有如下几点优势:

  1. 相比在系统内发送全局广播,它更高效。
  2. 不用担心别的应用伪造广播,造成安全隐患。
  3. 因广播数据在本应用内传播,没有隐私数据泄露的问题。

基本用法

创建LocalBroadcastManager对象LocalBroadcastManager manger= LocalBroadcastManager.getInstance(context) ;注册广播接收器LocalBroadcastManager.getInstance(context).registerReceiver(broadcastReceiver, intentFilter);发送广播LocalBroadcastManager.getInstance(context).sendBroadcast(intent);取消注册LocalBroadcastManager.unregisterReceiver(broadcastReceiver);

开发样例

package com.win.app;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.os.Bundle;import android.support.v4.content.LocalBroadcastManager;import android.support.v7.app.AppCompatActivity;import android.util.Log;public class MainActivity extends AppCompatActivity {    private LocalBroadcastManager mLocalManager;    private MyBroadcastReceiver mReceiver;    private IntentFilter mFilter;    private static final String ACTION = "com.win.test";    private static final String EXTRA_DATA= "data";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //注册广播接收器        mLocalManager= LocalBroadcastManager.getInstance(this) ;        broadcastReceiver = new WinBroadcastReceiver() ;        mFilter= new mFilter(ACTION) ;        mLocalManager.registerReceiver(mReceiver, intentFilter);        //发送广播,此时处在主线程中        Intent intent = new Intent(ACTION);        intent.putExtra(EXTRA_DATA, "主线程发来的");        mLocalManager.sendBroadcast(intent);        new Thread(new Runnable() {            @Override            public void run() {                //在子线程发送广播                Intent intent = new Intent(ACTION);                intent.putExtra(EXTRA_DATA, "消息来自于子线程" );                mLocalManager.sendBroadcast(intent);            }        }).start(); ;    }    private class WinBroadcastReceiver extends BroadcastReceiver {        @Override        public void onReceive(Context context, Intent intent) {            String action = intent.getAction();            if (ACTION.equals(action)){                Log.d("消息:" + intent.getStringExtra("data"), "线程: " + Thread.currentThread().getName());            }        }    }    @Override    protected void onDestroy() {        super.onDestroy();        // 取消注册广播,防止内存泄漏        mLocalManager.unregisterReceiver(mReceiver);    }}

源码剖析

 public class LocalBroadcastManager {    private static class ReceiverRecord {        final IntentFilter filter;        final BroadcastReceiver receiver;        boolean broadcasting;        ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver) {            filter = _filter;            receiver = _receiver;        }        @Override        public String toString() {            StringBuilder builder = new StringBuilder(128);            builder.append("Receiver{");            builder.append(receiver);            builder.append(" filter=");            builder.append(filter);            builder.append("}");            return builder.toString();        }    }    private static class BroadcastRecord {        final Intent intent;        final ArrayList<ReceiverRecord> receivers;        BroadcastRecord(Intent _intent, ArrayList<ReceiverRecord> _receivers) {            intent = _intent;            receivers = _receivers;        }    }    private static final String TAG = "LocalBroadcastManager";    private static final boolean DEBUG = false;    private final Context mAppContext;    private final HashMap<BroadcastReceiver, ArrayList<IntentFilter>> mReceivers            = new HashMap<BroadcastReceiver, ArrayList<IntentFilter>>();    private final HashMap<String, ArrayList<ReceiverRecord>> mActions            = new HashMap<String, ArrayList<ReceiverRecord>>();    private final ArrayList<BroadcastRecord> mPendingBroadcasts            = new ArrayList<BroadcastRecord>();    static final int MSG_EXEC_PENDING_BROADCASTS = 1;    private final Handler mHandler;    private static final Object mLock = new Object();    private static LocalBroadcastManager mInstance;    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);                }            }        };    }    /**     * Register a receive for any local broadcasts that match the given IntentFilter.     *     * @param receiver The BroadcastReceiver to handle the broadcast.     * @param filter Selects the Intent broadcasts to be received.     *     * @see #unregisterReceiver     */    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);            }        }    }    /**     * Unregister a previously registered BroadcastReceiver.  <em>All</em>     * filters that have been registered for this BroadcastReceiver will be     * removed.     *     * @param receiver The BroadcastReceiver to unregister.     *     * @see #registerReceiver     */    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);                        }                    }                }            }        }    }    /**     * Broadcast the given intent to all interested BroadcastReceivers.  This     * call is asynchronous; it returns immediately, and you will continue     * executing while the receivers are run.     *     * @param intent The Intent to broadcast; all receivers matching this     *     Intent will receive the broadcast.     *     * @see #registerReceiver     */    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();            final boolean debug = DEBUG ||                    ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);            if (debug) Log.v(                    TAG, "Resolving type " + type + " scheme " + scheme                    + " of intent " + intent);            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 (debug) Log.v(TAG, "Matching against filter " + receiver.filter);                    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 (debug) {                            String reason;                            switch (match) {                                case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;                                case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;                                case IntentFilter.NO_MATCH_DATA: reason = "data"; break;                                case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;                                default: reason = "unknown reason"; break;                            }                            Log.v(TAG, "  Filter did not match: " + reason);                        }                    }                }                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;    }    /**     * Like {@link #sendBroadcast(Intent)}, but if there are any receivers for     * the Intent this function will block and immediately dispatch them before     * returning.     */    public void sendBroadcastSync(Intent intent) {        if (sendBroadcast(intent)) {            executePendingBroadcasts();        }    }    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);                }            }        }    }}
0 0
原创粉丝点击