Android asynchronous thread principle, android thread

Source: Internet
Author: User

Android asynchronous thread principle, android thread
Basic Introduction

The Asynchronous Message Processing thread means that a thread enters a wireless loop body after it is started, and no cycle occurs once. One message is taken from the internal message queue, and calls back the corresponding message processing function. After a message is executed, the loop continues. If the message queue is empty, the thread is paused to know that there are new messages in the message queue.
The Asynchronous Message Processing thread is essentially a thread, but the Execution Code of this thread is set to the logic described above. In android, the implementation of asynchronous threads mainly involves the following classes: ThreadLocal, logoff, MessageQueue, Handler, and Message. Next we will introduce these classes one by one to parse the asynchronous thread mechanism of Android.
First, go to a frame chart:

ThreadLocal

ThreadLocal is not a class in the Android sdk, but a class in java. lang. This class is used to create a thread-based Variable storage for the thread. We can call it a local thread storage. ThreadLocal allows the object to achieve thread isolation. It maintains its own copy of variables for each thread and binds the variables to the thread through the set method. ThreadLocal provides a solution to the problem of multi-thread synchronization by copying each variable. In this way, each thread operates on its own variable, instead of a common variable, you do not need to synchronize the lock. For example, we create a variable which will be operated by two threads. In general, we will lock this variable to solve the synchronization problem through this method. But when we use ThreaLoca, we can use ThreadLoca to make a copy for every thread, and this copy is bound with the thread, that is to say, each thread can change its own variable without affecting another thread. In this way, no locks are required. ThreadLocal is automatically bound to the current thread when it is set, and does not need to be bound by itself. The code will not be written here, just know the central idea. Some may ask, what is the relationship between this and Android. This is about logoff, because in the asynchronous thread of Android, the thread variable bound to ThreadLocal is an object of logoff.

Logoff

What is the use of logoff? To Implement Asynchronous threads, logoff is required, because logoff is used to generate a MessageQueue. We can see from the source code that there is a member variable mQueue (MessageQueue class instance) in The logoff class. This variable is used to save MessageQueue In The logoff.
Logoff creates a MessageQueue object by using the static logoff. prepare () method. Note that the logoff. prepare () method can only be executed once in one thread.

Prepare () method

View 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));    }

The above is the android source code. When prepare is executed twice, an exception is thrown. This is actually very natural to think of, because as mentioned above, logoff is used to create MessageQueue. A thread can only have one MessageQueue. Therefore, there must be only one logoff object. After reading the source code of prepare (), it does not seem to have found that it has created an instance of MessageQueue. Yes, it cannot be seen here,. Let's take a look at what we did when creating a new logoff object:
We can find the logoff constructor:

    private Looper(boolean quitAllowed) {        mQueue = new MessageQueue(quitAllowed);        mRun = true;        mThread = Thread.currentThread();    }

We can find that the logoff constructor is private, and logoff only has this constructor. So we can see that we cannot create a logoff object in other classes. However, this is not the focus, and the focus is that logoff creates a MessageQueue object here.

Loop () method

The loop static method is used to execute a message loop. Everyone should know that this is an endless loop. It is used to continuously read messages in the message queue. Let's look at the source code: the source code is as follows:

    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;        // Make sure the identity of this thread is that of the local process,        // and keep track of what that identity token actually is.        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;            }            // This must be in a local variable, in case a UI event sets the logger            Printer logging = me.mLogging;            if (logging != null) {                logging.println(">>>>> Dispatching to " + msg.target + " " +                        msg.callback + ": " + msg.what);            }            msg.target.dispatchMessage(msg);            if (logging != null) {                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);            }            // Make sure that during the course of dispatching the            // identity of the thread wasn't corrupted.            final long newIdent = Binder.clearCallingIdentity();            if (ident != newIdent) {                Log.wtf(TAG, "Thread identity changed from 0x"                        + Long.toHexString(ident) + " to 0x"                        + Long.toHexString(newIdent) + " while dispatching to "                        + msg.target.getClass().getName() + " "                        + msg.callback + " what=" + msg.what);            }            msg.recycle();        }    }

The mylogoff function is used to return the logoff object of the current thread and execute a loop through a. Handler get is a Handler object. Put this in Handler and say

MessageQueue

MessageQueue is used to process message queues. There are several methods in this class. One is the next () method, which is used to retrieve the next element in the queue. The enqueueMessage method is used to add an element to the message queue. This method will be used in sendMessage in Handler. Here we will mention it a little. In sendMessage of Handler, this method will be called to add the Message to the MessageQueue of the receiving thread.

Handler

Handler is used to send information. We are familiar with the sendMessage method, which is used to send messages to the message receiving thread. As mentioned in the above frame chart, Handler must be created in the thread that receives the message. Only in this way can a message be sent to the thread. Because the created Handler Object handler must have the MessageQueue message queue of the thread to send messages to the thread. When Handler is created, the following constructor is used:

Handler Constructor
public Handler(Callback callback, boolean async) {        if (FIND_POTENTIAL_LEAKS) {            final Class<? extends Handler> klass = getClass();            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&                    (klass.getModifiers() & Modifier.STATIC) == 0) {                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +                    klass.getCanonicalName());            }        }        mLooper = Looper.myLooper();        if (mLooper == null) {            throw new RuntimeException(                "Can't create handler inside thread that has not called Looper.prepare()");        }        mQueue = mLooper.mQueue;        mCallback = callback;        mAsynchronous = async;    }

When Handler is created, The logoff object of the current thread is obtained through mlogoff = logoff. mylogoff ();, and The logoff object is the prerequisite for obtaining the MessageQueue object. When Handler calls handler. sendMessage (Message) to send a message, it will eventually call this method:

Handler's sendMessage method (the method that will be called eventually)
    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {        MessageQueue queue = mQueue;        if (queue == null) {            RuntimeException e = new RuntimeException(                    this + " sendMessageAtTime() called with no mQueue");            Log.w("Looper", e.getMessage(), e);            return false;        }        return enqueueMessage(queue, msg, uptimeMillis);    }

The handler obtains the MessageQueue object of the current thread. Call enqueueMessage (queue, msg, uptimeMillis). This method is the method in Handler, instead of the enqueueMessage method in MessgaeQueue. Let's check the enqueueMessage method in Handler:

EnqueueMessage in handler
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {        msg.target = this;        if (mAsynchronous) {            msg.setAsynchronous(true);        }        return queue.enqueueMessage(msg, uptimeMillis);    }

You can see the first line of code in the method body: msg.tar get = this;set the current message.tar get object to the current handler. In the logoff. loop () method, the msg.tar get. dispatchMessage (msg); method is called. This will be introduced soon. Let's not talk about this first. As you can see, the enqueueMessage method in handler sets the target of the message as the current object, and then calls the enqueueMessage of the MessageQueue object (this method was introduced in MessageQueue, is used to add a message to a message Queue) method, add the message to the MessageQueue object.
Now let's take a look at the handler's dispatchMessage (msg) method. Let's take a look at the source code of this method. This method will be used in logoff's loop method. When getting each message, it will call the msg.tar get method. dispatchMessage (msg); to process each message.

DispatchMessage
    public void dispatchMessage(Message msg) {        if (msg.callback != null) {            handleCallback(msg);        } else {            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);        }    }

In this method, first determine whether the message itself has a Callback function. If yes, call the Callback function of the message. If no, then determine whether the Callback interface is passed when the Handler is created. Note that, the name of this interface is Callback. Handler can assign a value to this mCallback through the constructor. If this mCallback is passed, this method is called; otherwise, the handleMessage method of Handler is called. This method is empty in Handler and needs to be rewritten in the class that inherits Handler. That is to say, this method is actually the lowest priority.
The latter two are common, but the former one, that is, the Message that carries the interface, is generally set through the Message. obtain (Handler h, Runnable callback) method.
Now, there are not many asynchronous threads in Android.

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.