The Android Message source code is described in detail.

Source: Internet
Author: User

The Android Message source code is described in detail.

I believe you are not familiar with Handler in Android, but you must know that Handler is only a shell in itself. What actually works internally is the Message class, for the Message class, I believe everyone will not be unfamiliar, just as you often use the Message. the obtain () method is the same. But do you know what operations the obtain () method has done for us? I will lead you to the Message kingdom to find out.

The first line of code is as follows:

public final class Message implements Parcelable

Needless to say, the Message implements the Parcelable interface, that is, the data encapsulated by the Message can be transmitted through Intent and IPC. Since the Parcelable interface is implemented, these three methods are essential in the Message method: 1) writeToParcel 2) describeContents 3) createFromParcel.

The following four member variables should be noted:

1) public int what

2) public int arg1

3) public int arg2

4) public Object obj


We often use such parameters, but do we really understand their true meanings? Google's internal comments are truly reliable.

1) The user defines the message identifier so that the system can identify what the current message is about. Each Handle has its own namespace for its own message identifier. Therefore, we do not have to worry about conflicts between Handler.

2) The second parameter has the same meaning as the third parameter, which is described in the annotation. If you only need to transmit simple int-type data, it is cheaper than setData (Bundle bundle.

3) The fourth parameter is interpreted as follows: This is a random data sent to the recipient, if Messager is used to send data for cross-process communication, the current obj cannot be a null pointer if Parcelable is implemented. For other data transmission, we generally use the setData method. However, for Versions later than android. OS. Build. VERSION_CODES # FROYO, The Parcelable object here is not supported.


After the preceding variables are completed, we need to explain the definition of another set of constants:

Private static final Object sPoolSync = new Object (); private static Message sPool; private static int sPoolSize = 0; // The Largest private static final int MAX_POOL_SIZE in the pond = 50;

At first glance, you may not understand the definitions of the above four variables. If I remind you that messages in Android can be reused, I believe that everyone can roughly guess the meaning of these four variables.

1. The first variable is actually used as a lock to prevent multiple threads from competing for resources and causing dirty data.

2. the sPool variable can be understood as a pointer to the header of the message queue.

3. sPoolSize indicates the length of the current message queue.

4. Define the maximum length of the cached message in the message queue.


OK. Here, the Message member variable has been explained, and the next step is to explain the Api methods.

The first method is the obtain method that is frequently used without any parameters:

public static Message obtain() {        synchronized (sPoolSync) {            if (sPool != null) {                Message m = sPool;                sPool = m.next;                m.next = null;                sPoolSize--;                return m;            }        }        return new CustomMessage();    }
First, to prevent multiple threads from competing for resources, lock sPoolSync. First, judge whether the pointer of the current queue is null. if the pointer is not empty, the message in the header of the current queue can be reused and retrieved, the header pointer of the current queue points to the next message of the current message, that is, m. next, set the tail pointer of the retrieved message to null, and the length of the queue is reduced by 1.

Method 2:

public static Message obtain(Message orig) {        Message m = obtain();        m.what = orig.what;        m.arg1 = orig.arg1;        m.arg2 = orig.arg2;        m.obj = orig.obj;        m.replyTo = orig.replyTo;        if (orig.data != null) {            m.data = new Bundle(orig.data);        }        m.target = orig.target;        m.callback = orig.callback;        return m;    }
We can see that this method has an orig parameter compared to the above method. From the code above, we can see that the Message object is first retrieved from the queue, then, copy the data of the parameter objects one by one, and finally return the objects.

The third method is as follows:

public static Message obtain(Handler h) {        Message m = obtain();        m.target = h;        return m;    }
Needless to say, this function specifies a Handler object for the currently created Message, because we know that Handler is the final destination of the Message.

public static Message obtain(Handler h, Runnable callback) {        Message m = obtain();        m.target = h;        m.callback = callback;        return m;    }
Compared with the above method, a row of m is added here. callback = callback. According to the description above, when some messages are actually executed, the callback Runnbale method will be triggered for execution.

The logic of a series of methods is similar. Let's explain one of them:

public static Message obtain(Handler h, int what, int arg1, int arg2) {        Message m = obtain();        m.target = h;        m.what = what;        m.arg1 = arg1;        m.arg2 = arg2;        return m;    }
That is to say, when creating a Message, some logical parameters can be provided for this Message.

When a message is created, the concept of recycle is inevitable. Let's take a look at the following:

public void recycle() {        clearForRecycle();        synchronized (sPoolSync) {            if (sPoolSize < MAX_POOL_SIZE) {                next = sPool;                sPool = this;                sPoolSize++;            }        }    }<pre name="code" class="java">void clearForRecycle() {        flags = 0;        what = 0;        arg1 = 0;        arg2 = 0;        obj = null;        replyTo = null;        when = 0;        target = null;        callback = null;        data = null;    }


In the clearForRecycle function, we perform some recycling pre-processing operations. The parameter set to 0 is set to 0, and the parameter set to null is set to null. In the recycle function, as long as the length of the current cache queue does not exceed the upper limit, add the current message to the end of the queue. 

The following method is required to implement Parcelable:

public static final Parcelable.Creator<CustomMessage> CREATOR            = new Parcelable.Creator<CustomMessage>() {        public Message createFromParcel(Parcel source) {            Message msg = Message.obtain();            msg.readFromParcel(source);            return msg;        }                public Message[] newArray(int size) {            return new Message[size];        }    };            public int describeContents() {        return 0;    }    public void writeToParcel(Parcel dest, int flags) {        if (callback != null) {            throw new RuntimeException(                "Can't marshal callbacks across processes.");        }        dest.writeInt(what);        dest.writeInt(arg1);        dest.writeInt(arg2);        if (obj != null) {            try {                Parcelable p = (Parcelable)obj;                dest.writeInt(1);                dest.writeParcelable(p, flags);            } catch (ClassCastException e) {                throw new RuntimeException(                    "Can't marshal non-Parcelable objects across processes.");            }        } else {            dest.writeInt(0);        }        dest.writeLong(when);        dest.writeBundle(data);        Messenger.writeMessengerOrNullToParcel(replyTo, dest);    }    private void readFromParcel(Parcel source) {        what = source.readInt();        arg1 = source.readInt();        arg2 = source.readInt();        if (source.readInt() != 0) {            obj = source.readParcelable(getClass().getClassLoader());        }        when = source.readLong();        data = source.readBundle();        replyTo = Messenger.readMessengerOrNullFromParcel(source);    }

OK. The analysis of the kernel source code of Message will be explained here. I believe you will have a deeper understanding when using this class later.





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.