欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android消息机制(3)- Handler和Looper

程序员文章站 2022-07-14 19:58:37
...

Looper

Looper主要的作用是,不断的从MessageQueue中取出Message,交给Message的target(Handler)处理。
打开Looper的源码,发现一段注释的代码:

  * <pre>
  *  class LooperThread extends Thread {
  *      public Handler mHandler;
  *      public void run() {
  *          // 初始化Looper
  *          Looper.prepare();
  *          // 初始化Handler
  *          mHandler = new Handler() {
  *              public void handleMessage(Message msg) {
  *                  // process incoming messages here
  *              }
  *          };
  *          // Looper不断取Message
  *          Looper.loop();
  *      }
  *  }</pre>

这是怎么在子线程中,正确的使用消息机制的代码。
先看看Looper.prepare();做了什么:

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
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");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}

注意 ThreadLocal ,按我自己的理解,他内部保存一个Map,Key为线程,Value是你要保存的值。使用ThreadLocal,可以保证一个线程,只有一个副本。sThreadLocal被声明为ThreadLocal,也就说明一个线程只有一个Looper。
接着我们看看Looper.loop();做了什么:

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);
        }
        // 交给Handler处理消息
        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);
        }
        // 回收Message
        msg.recycle();
    }
}
public static Looper myLooper() {
   return sThreadLocal.get();
}

Looper.loop()其实就是一直从MessageQueue取出消息,有就交给target(Handler)处理,没有就阻塞。代码很简单,原理也不难,但是Looper非常重要。
额外还要知道之前说过一个东西,叫“同步分割栏”,在Looper中,代码为:

// 设置同步分割栏
public int postSyncBarrier() {
    return mQueue.enqueueSyncBarrier(SystemClock.uptimeMillis());
}
// 取消同步分割栏
public void removeSyncBarrier(int token) {
    mQueue.removeSyncBarrier(token);
}

Handler

Handler是消息的产生者和消费者。Handler会将Message加入MessageQueue中,Looper不断地从MessageQueue中取出Message,交给target的Handler处理。
先看看Handler的构造函数,主要的有2个:

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

如果我们new一个Handler实例时,没有指定Looper的话,默认使用当前线程Looper。但是如果当前线程的Looper还没有初始化,就会报错。所以我们在示例中,要先调用Looper.prepare();初始化。mCallback是一个接口,代码:

public interface Callback {
    public boolean handleMessage(Message msg);
}

再看看Handler处理消息的代码:

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        // 如果mCallback不为null,消息直接交给mCallback处理
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

所以我们new一个Handler不一定要重写handleMessage(Message)方法,还可以设置mCallback来处理消息。
再从构造函数有一个mAsynchronous,这是就是设置同步/异步,暂时先不用太在意。
我们再来看看Handler怎么“发送”Message到MessageQueue,代码:

public final boolean post(Runnable r) {
   return  sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postAtTime(Runnable r, long uptimeMillis) {
    return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
public final boolean postAtTime(Runnable r, Object token, long uptimeMillis) {
    return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}
public final boolean postDelayed(Runnable r, long delayMillis) {
    return sendMessageDelayed(getPostMessage(r), delayMillis);
}
public final boolean postAtFrontOfQueue(Runnable r) {
    return sendMessageAtFrontOfQueue(getPostMessage(r));
}
public final boolean sendMessage(Message msg) {
    return sendMessageDelayed(msg, 0);
}
public final boolean sendEmptyMessage(int what) {
   return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
    Message msg = Message.obtain();
    msg.what = what;
    return sendMessageDelayed(msg, delayMillis);
}
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
    Message msg = Message.obtain();
    msg.what = what;
    return sendMessageAtTime(msg, uptimeMillis);
}

从代码可以看出,postXXX和sendXXX最终都调用了sendMessageDelayed和sendMessageAtTime这两个方法。我们先看看sendMessageDelayed方法:

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

sendMessageDelayed方法最终调用了sendMessageAtTime,所以正真的大Boss是sendMessageAtTime,看看:

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) {
    // 把目标设置为自己
    msg.target = this;
    // 设置同步/异步
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    // 加入到MessageQueue中
    return queue.enqueueMessage(msg, uptimeMillis);
}

然后我们看看Looper取出之后,Handler处理消息的代码(其实上面已经有了):

// Looper代码片段: 取出Message,调用target的dispatchMessage方法处理消息
msg.target.dispatchMessage(msg);

// Handler的dispatchMessage方法
public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        // post(Runnable)在这里处理
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            // return true就不执行重写的handleMessage
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        // 我们继承Handler的子类重写的handleMessage方法
        handleMessage(msg);
    }
}
private static void handleCallback(Message message) {
    message.callback.run();
}

dispatchMessage方法内,首先看看Message的Callback有没有,那么Message的Callback什么时候才不为null呢?答案在这里:

public final boolean post(Runnable r) {
   return  sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;
    return m;
}

当我们使用Handler.post(Runnable)时,此时Message的callback就是Runnable,这下理解了吧。虽然使用了很多次,这下终于知道原理了。
接着看dispatchMessage,之前也说了mCallback,如果mCallback没有处理,那么我们声明Handler时重写的handleMessage方法就会执行。Handler处理消息就这么简单。