Android Handler 工作原理

Handler、Message、MessageQueue、Looper

1.Looper.prepare();

public static void prepare() {
    prepare(true);
}

private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
//这里创建的Looper
 sThreadLocal.set(new Looper(quitAllowed));
}


private Looper(boolean quitAllowed) {
  //这里创建的MessageQueue
  mQueue = new MessageQueue(quitAllowed);
   mThread = Thread.currentThread();
}

平时我们在主线程和子线程之间切换没调用Looper.prepare();是因为Activity创建的时候已经调用过Looper.prepareMainLooper();

2.Looper.loop();

public static void loop() {
    final Looper me = myLooper();
    if (me == null) {
    //这个错误很多人应该见过,是因为没有调用Looper.perpare()就调用Looper.loop()
     throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;

  //这里是个死循环
    for (;;) {
    //这里获取到Message
     Message msg = queue.next();
     //当msg为null才会退出,调用quit方法退出时会在消息队列里加入一个null的msg
     if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }

      //...此处省略代码

     try {
     //msg.target 就是发送消息的Handler,调回到Handler的dispatchMessage方法里了
      msg.target.dispatchMessage(msg);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
        } finally {
    if (traceTag != 0) {
     Trace.traceEnd(traceTag);
     }
     }  
      //...此处省略代码
     }}

3.Message

好像没啥说的,或者不知道怎么说。。。。

While the constructor of Message is public, the best way to get
* one of these is to call {@link #obtain Message.obtain()} or one of the
* {@link Handler#obtainMessage Handler.obtainMessage()} methods, which will pull
* them from a pool of recycled objects.

这里是官方的注释,官方建议使用Message.obtain()方法来获取Message

4.new Handler()

//最常用的构造方法
public Handler() { this(null, false);}

 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) {
    //这个错都见过吧?就是因为没有调用Looper.prepare()
 throw new RuntimeException(
 "Can't create handler inside thread that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

5.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, SystemClock.uptimeMillis() + delayMillis);
    }
    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);
    }
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
	//将Handler放入target里,后面消息分发时就会使用msg.target.dispatchMessage(msg);
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
	//将消息加入消息队列中
        return queue.enqueueMessage(msg, uptimeMillis);
    }



以常用的子线程向主线程发送消息为例,梳理下逻辑

  1. Activity初始化时帮我们调用的了Looper.prepare(),这里创建了Looper和MessageQueue
  2. Activity初始化时也帮我们调用了Looper.loop(),进入死循环一直在调用queue.next()获取消息
  3. 发送消息,最终通过queue.enqueueMessage(msg, uptimeMillis);  将消息加入消息队列中
  4. 死循环中获取到刚刚发送的消息通过queue.next(); 方法获取到消息
  5. 获取到消息通过msg.target.dispatchMessage(msg);分发到Handler

扯了半天,怎么切换的线程?


这里依靠的是ThreadLocal,简单的说它只属于自己的线程,即使是同一个ThreadLocal对象,也可以在不同的线程中获取到不同的值,想专门了解这个的可以自行查找,这里不做长篇叙述。

Looper类中有

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
在Looper.perpare()中
sThreadLocal.set(new Looper(quitAllowed));

还是以子线程向主线程发送消息为例

此时的Looper.perpare()和Looper.loop()都还是在主线程也就是UI线程中被调用,因为是Activity初始化时已经帮我们调用了Looper.perpare()和Looper.loop(),所以不需要我们手动调用了。

向主线程发送消息,所以我们的Handler要创建在主线程里,在上面Hnadler的构造方法里有

mLooper = Looper.myLooper();

因为上述介绍到ThreadLocal的特性,同在主线程中,所以获取到的即为在Looper.perpare()中创建的Looper对象

在子线程中发送消息出去,消息被放入消息队列中,Looper对象是相同的,而所使用的消息队列是Looper对象的私有属性,也没有发生变化,所以MessgeQueue也是相同的,之在Looper.loop()方法中发送的消息通过queue.next()方法被获取到,在Looper.loop()方法中调用了 msg.target.dispatchMessage(msg)方法,而Looper.loop()方法是在主线程中调用的,所以最终Handler中的dispatchMessage方法就是在主线程中调用的了。




猜你喜欢

转载自blog.csdn.net/du_zilin/article/details/80496552