ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
#### 10.2.4 Handler的工作原理 **[Handler](https://www.androidos.net.cn/android/6.0.1_r16/xref/frameworks/base/core/java/android/os/Handler.java)的工作主要包含消息的发送和接收过程**。消息的**发送可以通过post的一系列方法以及send的一系列方法来实现,post的一系列方法最终是通过send的一系列方法来实现的**。 发送一条消息的典型过程如下所示。 ``` 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) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); } ``` 可以发现,**Handler发送消息的过程仅仅是向消息队列中插入了一条消息**,**MessageQueue的next方法就会返回这条消息给Looper(Looper.loop方法内部调用了MessageQueue的next方法), Looper收到消息后就开始处理了,最终消息由Looper交由Handler处理,即Handler的dispatchMessage方法会被调用,这时Handler就进入了处理消息的阶段**。dispatchMessage的实现如下所示。 ``` public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } ``` **Handler处理消息的过程**如下: 首先,检查Message的callback是否为null,不为null就通过handleCallback来处理消息。**Message的callback是一个Runnable对象,实际上就是Handler的post方法所传递的Runnable参数**。handleCallback的逻辑也是很简单,如下所示。 ``` private static void handleCallback(Message message) { message.callback.run(); } ``` 其次,**callback(就是Handler的post方法所传递的Runnable参数)为null,再检查mCallback是否为null,不为null就调用mCallback的handleMessage方法来处理消息**。Callback是个接口,它的定义如下: ``` /** * Callback interface you can use when instantiating a Handler to avoid * having to implement your own subclass of Handler. * * @param msg A {@link android.os.Message Message} object * @return True if no further handling is desired */ public interface Callback { public boolean handleMessage(Message msg); } ``` **通过Callback可以采用如下方式来创建Handler对象**:`Handler handler = new Handler(callback)`。那么**Callback的意义是什么呢?源码里面的注释已经做了说明:可以用来创建一个Handler的实例但并不需要派生Handler的子类**。 **在日常开发中,创建Handler最常见的方式就是派生一个Handler的子类并重写其handleMessage方法来处理具体的消息,而Callback给我们提供了另外一种使用Handler的方式,当我们不想派生子类时,就可以通过Callback来实现**。 最后,**调用Handler的handleMessage方法来处理消息**。Handler**处理消息的过程**可以归纳为一个流程图,如图10-2所示。 :-: ![](https://img.kancloud.cn/d7/fb/d7fb753a94bd9b8a1fafc12b75c20720_474x613.png) 图10-2 Handler消息处理流程图 **Handler还有一个特殊的构造方法,那就是通过一个特定的Looper来构造Handler**,它的实现如下所示。通过这个构造方法可以实现一些特殊的功能。 ``` /** * Use the provided {@link Looper} instead of the default one. * * @param looper The looper, must not be null. */ public Handler(Looper looper) { this(looper, null, false); } ``` 下面看一下Handler的一个默认构造方法public Handler(),这个构造方法会调用下面的构造方法。很明显,如果当前线程没有Looper的话,就会抛出“Can't create handler inside thread that has not called Looper.prepare()”这个异常,这也解释了在没有Looper的子线程中创建Handler会引发程序异常的原因。 ``` 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; } ```