【Android】Handler是如何切换线程的?

时间:2025-01-27 08:26:22

1、问题:handler是如何切换线程的?

想要了解这个问题,需要知道Handler、Message、MessageQuene、Looper之间的关系:

首先Message由Handler生成并放入MessageQuene中,Looper持有MessageQuene并不停的尝试从中取出Message交由Handler处理。

2、我们从代码角度看一下一个主线程发出的Message在子线程被执行的流程:

2.1 首先在创建一个HandlerThread线程,它的特点是run方法生成一个Looper

  thread = new HandlerThread("handler_thread#");
  ();

看一下HandlerThread#run都执行了什么操作:


    public void run() {
        mTid = ();
        ();
        synchronized (this) {
            mLooper = ();
            notifyAll();
        }
        (mPriority);
        onLooperPrepared();
        ();
        mTid = -1;
    }

首先生成了一个Looper对象并持有这个对象的引用,然后调用()开启Looper的无限循环。

Looper#loop()

//该方法执行在调用次方法的线程中,也就是HandlerThead.
    public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; () wasn't called on this thread.");
        }
        final MessageQueue queue = ;
		//省略部分代码
        for (;;) {
		    //不停的从MessageQueue取出message
            Message msg = (); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
		  //省略部分代码
            try {
			//一旦message不为空则交由handler处理这个消息。
                (msg);
                dispatchEnd = needEndTime ? () : 0;
            } finally {
                if (traceTag != 0) {
                    (traceTag);
                }
            }
        }
    }

从上面代码可以看出,Looper从MessageQuene中获取到messge之后交给message的目标handler处理这个message。因为Looper#loop()在HandlerThread线程中执行,所以handler的处理过程也是在HandlerThread线程中执行。

2.2 生成一个handler绑定HandlerThread生成的Looper对象

threadHandler = new Handler(()){
                @Override
                public void handleMessage(Message msg) {
                    (msg);
                    //子线程handler接收到消息,开始处理任务
                    collectInfo("threadHandler接收到消息开始处理");
                    (2000);
                    //告诉UI handler任务完成的消息
                    collectInfo("子线程处理好任务了");
                }
            };

在这个threadHandler对象的handleMessage()方法中处理Looper传过来的Message。由于Looper#loop()在HandlerThread线程中执行,所以handler的handleMessage处理过程也是在HandlerThread线程中执行

2.3 我们在主线程中调用threadHanlder的发送message的方法

(1).sendToTarget();

此时发动消息是执行在主线程的,我们看下发送的代码流程:

Handler#obtainMessage

 public final Message obtainMessage(int what)
    {
        return (this, what);
    }

Message#obtain

public static Message obtain(Handler h, int what) {
        Message m = obtain();
         = h;
         = what;

        return m;
    }

Message#sendToTarget

/**
     * Sends this Message to the Handler specified by {@link #getTarget}.
     * Throws a null pointer exception if this field has not been set.
     */
    public void sendToTarget() {
        (this);
    }

target是Handler,此时又回到了handler#sendMessage

public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }


public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, () + delayMillis);
    }


 public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            ("Looper", (), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }


 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
         = this;
        if (mAsynchronous) {
            (true);
        }
        return (msg, uptimeMillis);
    }

我们继续看一下MessageQuene#enqueueMessage

boolean enqueueMessage(Message msg, long when) {
       //省略部分代码
        synchronized (this) {
            ();
             = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < ) {
                // New head, wake up the event queue if blocked.
                 = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                needWake = mBlocked &&  == null && ();
                Message prev;
                for (;;) {
                    prev = p;
                    p = ;
                    if (p == null || when < ) {
                        break;
                    }
                    if (needWake && ()) {
                        needWake = false;
                    }
                }
                 = p; // invariant: p == 
                 = msg;
            }
			//省略部分代码
        }
        return true;
    }

从代码可以看出,此方法就是把消息按照时间顺序放入MessageQuene中(此时是在主线程执行)等待被()的无限循环获取方法取出并传给handler处理(此时是在HandlerThread线程中执行)。至此消息在主线程生成在HandlerThread线程被执行的过程就完成了。

完整的演示demo代码地址:/zhaohe9981/