Secret Localbroadcastmanager Implementation principle

Source: Internet
Author: User

Localbroadcastmanager frequently used in-app communication components, also officially recommended in-app broadcast send components
at first, when using this component, the name is known, because Localbroadcast, so thought is also used binder to achieve the bottom, the result is not this.
1, usually we are so with LocalbroadcastmanagerA, register and receive
Localbroadcastmanager Broadcastmanager = localbroadcastmanager.getinstance (context); Intentfilter IntentFilter = new Intentfilter (); Intentfilter.addaction (ACTION), mreceiver = new Broadcastreceiver () {@Overridepublic void OnReceive ( Context context, Intent Intent) {String Key = Intent.getextras (). getString ("key"), if ("Key". Equals (Key)) {log.i ("tag", " Receive the broadcast ");}}; Broadcastmanager.registerreceiver (Mreceiver, Intentfilter);

b. Send broadcast
Localbroadcastmanager.getinstance (context). Sendbroadcast (New Intent (ACTION));

c. Cancellation of registration
Localbroadcastmanager.getinstance (context). Unregisterreceiver (Mreceiver);


2, how to achieve? A, asynchronous to the source:Localbroadcastmanager.java See how it is implemented in the end, the standard single-instance implementation:
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:executepen                        Dingbroadcasts ();                    Break                Default:super.handleMessage (msg);    }            }        }; }

a new instantiation of the Looper (Context.getmainlooper ()) based on the main thread calls the receiver to process the broadcast message in a Handler,handlemessage method.

B, registered to receive
/** * 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); }        }    }
registers the storage broadcast and filtering information to Broadcastreceiver to Key,intentfilter as value and stores it to ArrayList.
here Mreceivers, why the saved Intentfilter is ArrayList form, the Intentfilter is able to save multiple action, which is why he initialized to a 1-length list. The ArrayList here can pass in multiple intentfilter, though, but if the action is the same, it will come out as one. The action is stored as a key.
c. Cancellation of registration
/** * Unregister a previously registered broadcastreceiver.     <em>All</em> * Filters that has been registered for this broadcastreceiver would be is * 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.remo                        ve (action); }                    }                }            }        }    }
just remove the corresponding elements from Mreceivers and mactions.
D, should look at this time executependingbroadcasts () method source code:
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);                }            }        }    }
This function, mpendingbroadcasts to broadcastrecord[], loops through each receiver, invokes broadcast's OnReceive function, and completes the broadcast logic. Message processing is complete.

e, how to send the broadcast
 /** * Broadcast the given intent to all interested broadcastreceivers. This * call is asynchronous;     It returns immediately, and you'll continue * executing while the receivers is run. * * @param intent the intent to broadcast;     All receivers matching this * Intent would 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"; 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 didNot match: "+ reason); }}} if (receivers! = null) {for (int i=0; i<rece Ivers.size ();                    i++) {receivers.get (i). Broadcasting = FALSE;                    } mpendingbroadcasts.add (New Broadcastrecord (intent, receivers)); if (!mhandler.hasmessages (msg_exec_pending_broadcasts)) {Mhandler.sendemptymessage (Msg_exec_pendin                    g_broadcasts);                } return true;    }}} return false; }

Remove the Receiverrecord list from mactions according to action, looping through each Receiverrecord to determine the action\type\scheme\data\ in the filter Categoried whether match, matches the words to save to receivers, then sends the empty message, what=msg_exec_pending_broadcasts, this time handler will go to deal with.
Summary:A, registration and anti-registration consistency, OnStart, OnStopB, a broadcast, it is best to put the action in a intentfilter. C, Localbroadcastmanager only the registration to the role of interaction. D, the core of Localbroadcastmanager is handler, using the match function of Intentfilter. E, handler implementation of intra-code communication, he holds broadcastreceiver objects, directly call the OnReceive method, security efficiency high.

Secret Localbroadcastmanager Implementation principle

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.