Android asynchronous messaging mechanism

Source: Internet
Author: User

The asynchronous messaging mechanism in Android is divided into four parts: message, Handler, MessageQueue, and Looper.

Where the message is the messages passed between threads, the What, Arg1, arg2 fields can carry integer data, and the Obj field can carry an object.

Handler is a processor that is used primarily for sending messages and processing messages. The method of sending a message is SendMessage; The message is processed by Handlemessage (), and the information carried by the message field is used as a discriminant in the method.

MessageQueue is a message queue that holds messages sent by all handler.

Looper is the "steward" of the message queue, taking the message out of the message queue and assigning it to the handler Handlemessage () method.

————————————————————————————————————————————————————————————————————————————————

The flow of asynchronous message processing is:

① first, you need to create a handler object in the main thread and override the Handlemessage () method.

② when a child thread finishes processing a time-consuming operation and needs to feed the results back into the UI, a Message object is created and the What field carries an int value and is then sent through the handler object.

After ③ the message is added to MessageQueue waiting to be processed, Looper tries to remove the pending message from MessageQueue and finally distributes it back to the handler () method in the Handlemessage object. Because the handler object is created in the main thread, it is safe to perform UI operations in the Handlemessage () method.

————————————————————————————————————————————————————————————————————————————————

Verify with an example: there is a button and a textview in the active mainactivity. TextView initialization displays "Hello world!", then clicks the button, takes the time-consuming operation, after the time-consuming operation finishes, TextView displays "Nice to meet you". Based on the above analysis, I wrote the following code in an incredibly natural way:

 Packagecom.shaking.androidthreadtest;ImportAndroid.os.Handler;ImportAndroid.os.Message;Importandroid.support.v7.app.AppCompatActivity;ImportAndroid.os.Bundle;ImportAndroid.view.View;ImportAndroid.widget.Button;ImportAndroid.widget.TextView; Public classMainactivityextendsAppcompatactivityImplementsview.onclicklistener{Private Static Final intUpdate_text=1; PrivateString data; PrivateTextView TextView; PrivateHandler handler=NewHandler () {@Override Public voidhandlemessage (Message msg) {Switch(msg.what) { CaseUPDATE_TEXT:textView.setText (data);    }        }    }; @Overrideprotected voidonCreate (Bundle savedinstancestate) {Super. OnCreate (savedinstancestate);        Setcontentview (r.layout.main_layout); Button Button=Findviewbyid (R.id.button); TextView=Findviewbyid (R.id.text_view); Button.setonclicklistener ( This); } @Override Public voidOnClick (view view) {NewThread (NewRunnable () {@Override Public voidrun () {//assuming the time-consuming operation here, the result string is finally obtained dataData= "Nice to meet"; Message Message=NewMessage (); Message.what=Update_text;            Handler.sendmessage (message);    }}). Start (); }}

First of all, it's certainly no mistake to write like this! The program can also run normally. However, the IDE gives a warning: "This Handler class should is static or leaks might occur".

This warning means: When we use the handler class, we should declare it as static, otherwise it will cause a memory leak.

So why is there a memory leak? The reasons are:

First: When we send a message object through the SendMessage () method of the Handler object, the Message object holds a reference to the handler object, which relies on this reference, and looper the message object out of the queue, To accurately assign the message object back to the handler object! )。

Second, when we create the handler object in the main thread, in order to override its Handlemessage () method, an anonymous inner class is used to create the handler object. Anonymous inner and non-static inner classes are implicitly holding a reference to an external class! Therefore, the handler object holds a reference to the external class mainactivity.

With these two together, the problem is: The message object holds the handler object reference, and the handler object holds the Mainactivity reference. So, mainactivity the activity can never be reclaimed by memory until the message is recycled! If the message object is sent in a child thread to a queue of messages, and then is not processed, the main thread of the activity is always hanging, not being reclaimed by memory. Therefore, memory leaks are caused.

————————————————————————————————————————————————————————————————————————————————

Know the reason, then what is the solution? In fact, previous warnings have given the solution. That is to create a handler object by means of a static inner class, because the static inner class does not hold a reference to the external partial object.

At this point, I naturally create a static inner class, inherit from the handler class, and then rewrite its Handlemessage method.

Private Static class extends handler{        @Override        publicvoid  handlemessage (Message msg) {                                        }    } 

However, there is another problem here! If I don't have a reference to an external class, how do I use the methods and objects of the external classes? After all, I'm going to do the UI operation in the Handlemessage () method.

For this use of static internal classes to avoid memory leaks, but also the need to invoke methods of the external class: You can use weak references! That is, we declare a weak reference to an external class object in the inner classes. This means that the method of the external class can be called without causing a memory leak.

The specific modified code is as follows:

 Packagecom.shaking.androidthreadtest;ImportAndroid.os.Handler;ImportAndroid.os.Message;Importandroid.support.v7.app.AppCompatActivity;ImportAndroid.os.Bundle;ImportAndroid.view.View;ImportAndroid.widget.Button;ImportAndroid.widget.TextView;Importjava.lang.ref.WeakReference; Public classMainactivityextendsAppcompatactivityImplementsview.onclicklistener{Private Static Final intUpdate_text=1; PrivateString data; PrivateTextView TextView; Private Static classMyHandlerextendshandler{//causes the inner class to hold a weak reference to the external partial        PrivateWeakreference<mainactivity>WeakReference; //completion of weak reference initialization in the constructorMyHandler (mainactivity activity) {WeakReference=NewWeakreference<>(activity); } @Override Public voidhandlemessage (Message msg) {//get a reference to an external class object by using the Get () method of a weak referenceMainactivity activity=Weakreference.get ();        Activity.textView.setText (Activity.data); }    }    //Create a Handler object    PrivateMyHandler handler=NewMyHandler ( This); @Overrideprotected voidonCreate (Bundle savedinstancestate) {Super. OnCreate (savedinstancestate);        Setcontentview (r.layout.main_layout); Button Button=Findviewbyid (R.id.button); TextView=Findviewbyid (R.id.text_view); Button.setonclicklistener ( This); } @Override Public voidOnClick (view view) {NewThread (NewRunnable () {@Override Public voidrun () {//assuming the time-consuming operation here, the result string is finally obtained dataData= "Nice to meet"; Message Message=NewMessage (); Message.what=Update_text;            Handler.sendmessage (message);    }}). Start (); }}

Solve all the above problems perfectly! 6~

Finally, it is recommended to use the final solution directly: Static inner class + weak reference.

Android asynchronous messaging mechanism

Related Article

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.