Android Message Processing Mechanism-Logoff, Handler and Message Analysis
Digress:
To put it bluntly, the preliminary understanding of the three was actually on the back of the questions. At that time, it was not long before I got into touch with Android. The books I learned were the crazy Android handouts that were suitable for beginners. Of course, when I learned Handler, some simple examples are also mentioned in the book. Later, when MessageQueue was used in my work, I began to figure out the relationship between the three. If you want to have a good understanding of the three, I personally recommend "deep understanding Android volume I". The following is a reference to the relevant chapters in this book.
Overview:
The message passing mechanism of Android is another form of "event processing". This mechanism is mainly used to solve the problem of multithreading in Android applications. The Android platform only allows the UI thread to modify the UI components in the Activity, this makes it impossible for the newly started thread to dynamically modify the attribute values in the interface component. However, our program interface cannot be a static presentation, so we must use the three categories mentioned in this blog.
Simple Example: Code display:
Public class LooperThreadActivity extends Activity {private final int MSG_HELLO = 0; private Handler mHandler; private CustomThread mThread = null; private static final String TAG = LooperThreadActivity. class. getSimpleName (); @ Override public void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. main); mThread = new CustomThread (); mThread. start (); Button sendButton = (Button) findViewById (R. id. send_button); final EditText contentEditText = (EditText) findViewById (R. id. content_edittext); sendButton. setOnClickListener (new OnClickListener () {@ Override public void onClick (View v) {String msgText = contentEditText. getText (). toString (); sendMessage (msgText) ;}}) ;}private void sendMessage (String content) {Toast. makeText (this, send msg: + content, 0 ). show (); // TODO 1. add a Message to MessageQueue // use Message. obtain () is used to obtain empty message objects from the message pool to save resource logs. I (TAG, ------------> send msg 1 .); message msg = mHandler. obtainMessage (MSG_HELLO, content); msg. sendToTarget (); Log. I (TAG, ------------> send msg 2 .); message msg2 = mHandler. obtainMessage (MSG_HELLO, content + 2); msg2.sendToTarget ();} class CustomThread extends Thread {@ Override public void run () {Looper. prepare (); Log. I (TAG, ------------> loop. pre .); mHandler = new Handler () {public void handleMessage (Message msg) {switch (msg. what) {case MSG_HELLO: Log. I (TAG, ------------> receive msg .); toast. makeText (LooperThreadActivity. this, receive msg: + (String) msg. obj, 0 ). show () ;}}; logoff. loop ();}}}
Running Effect display:
Log result display:
Sample result analysis:
As you can see, I have added message data twice in a row and the results are also very good, but the content between lorule. prepare (); and Handler is only executed once. This is because the custom thread CustomThread is started only once, and has existed since the start and has not been destroyed. Therefore, the logoff always exists and MessageQueue always exists, this ensures that a Thread can have only one loose object. The source code will be used for further explanation.
Mechanism Analysis:
As far as applications are concerned, the Java applications in the Android system are the same as those in other systems and work by message drivers. The Message drivers in the Android system cannot be separated from logoff, Handler, and Message. Although it is not important, what is more prominent is logoff. The following describes these classes one by one.
Lorule analysis: 1. lorule. prepare ();
Tracking prepare () into the Android source code, we can find the following source code:
private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException(Only one Looper may be created per thread); } sThreadLocal.set(new Looper(quitAllowed)); }
SThreadLocal definition:
// sThreadLocal.get() will return null unless you've called prepare().static final ThreadLocal
sThreadLocal = new ThreadLocal
();
From the source code above, we can see that a logoff object is set in the thread that calls prepare, and The logoff object is saved in the TLV of the calling thread. The logoff object encapsulates a message queue. That is to say, prepare uses the ThreadLocal mechanism to associate logoff with the call thread.
2. logoff. loop ();
The tracking loop () enters the Android source code (some temporarily unrelated code is deleted here ):
public static void loop() {final Looper me = myLooper(); if (me == null) { throw new RuntimeException(No Looper; Looper.prepare() wasn't called on this thread.); } final MessageQueue queue = me.mQueue; Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } msg.target.dispatchMessage(msg); msg.recycle(); }}
Through the above analysis, logoff has the following functions:
Encapsulates a message queue. the prepare function binds the current logoff and the thread that calls prepare (that is, the final processing thread) together. the processing thread calls the loop to process messages from the message queue. when the event SOURCE sends a message to the logoff, it actually adds the message to the logoff message queue. Then, the message will be processed by the logoff binding.
Handler Class Analysis:
When learning Handler, let's first get to know some of the Handler's members:
final MessageQueue mQueue;final Looper mLooper;final Callback mCallback;
In the Handler class, its constructor will point the Message Queue variable in Handler to The logoff message queue. Because it is directed, the message queue in Handler is actually a loose message queue.
Description of the synchronization relationship between logoff and Handler and the introduction of HandlerThread:
There is actually a synchronization relationship between logoff and Handler. The synchronization relationships between them are not described too much here. If you want to learn more, please refer to "deep understanding Android volume I" Page 128th. The author only provides one reminder: HandlerThread perfectly solves the NULL pointer exception problem that may occur during logoff and Handler synchronization, so in the future development process, we should use HandlerThread more. Of course, if you don't want to use it, use the lock mechanism to make your code robust, but this may cause repeated wheel tongue.
Conclusion:
Although it has been "confused" to the end, but the understanding of logoff, Handler and Message is indeed a huge step. I hope you will have some gains after reading this article.