Summary of Android Thread, Handler, Loop, Message, Handler Thread

Keywords: Java

Question:
1:Handle Thread Loop,MessageQueue relationship, how do they bind?

2: How do you specify threads to process messages sent by Handle?

3: How to use the difference between Handler Thread and Thread?

==================================================
Analysis:
Thread is a common thread class that can be used independently, just like java.

Loop: The loop, which holds a thread and follows a MessageQueue, turns Thread into HandleThread, which is the thread that works in a loop. In the process of program development (especially in GUI development), we often need a thread to keep looping. Once there is a new task, it will be executed, and the execution will continue to wait for the next task.

handle: Message Sending, Processor, Binding a Loop, Sending Message is executed by Loop and put into MessageQueue, Loop takes it out and handles it at a specific time.

Binding relationship:
1:handler initialization binds a Loop, which by default gets the current thread's Loop.

public Handler(Looper looper, Callback callback, boolean async) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}
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) {
        }
    }
    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;
}

So the specified Loop can be passed in when the handler is initialized, and then the message sent by the handler will be handed over to the Loop! Without the handler, the Loop bound to the current thread will be fetched!

2:Loop
Loop.prepare() binds the current thread and creates a new MessageQueue

//Loop static member properties
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//loop.prepare()
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));
}
//Constructor
private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}

Summary relationship:
1:handler holds a Loop (with and without one, default to a Loop bound to the current thread);
2:Loop holds Thread (yes and only one), and MessageQueue; (yes and only one)
3:Loop.prepare() binds the current thread and creates a new MessageQueue
4: A Loop can be held by multiple handler s!!
5: The Message message Message sent by handler knows how to bind its own tag. The next time Loop takes out the Message, it will follow the bound tag and return it to the corresponding handler.

Relationships: Multiple handler s correspond to one Loop, one thread corresponds to one MessageQueue!

Handler Thread: Cyclic processing message threads, internal binding with Loop, external providing the loop of this thread,
Used in conjunction with Handle, the thread can be obtained to initialize Loop when Handle is initialized.

//Handler Thread run method:
@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}
//Get Loop
public Looper getLooper() {
    if (!isAlive()) {
        return null;
    }

    // If the thread has been started, wait until the looper has been created.
    synchronized (this) {
        while (isAlive() && mLooper == null) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
    }
    return mLooper;
}

Use:

//Create circular threads
HandlerThread handlerThread= new HandlerThread("tag");
handlerThread.start();

//Initialize the loop that Handler passes into Handler Thsread
Handler handler=new Handler(handlerThread.getLooper()){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//TODO where the code will be executed in the handler Thread sub-thread!!!

}
};

In this way, messages sent using handle will be processed by HandlerThread, and handlerThread will block polling until the quit() method is called!

Posted by sgboise on Wed, 12 Dec 2018 12:24:06 -0800