原创源码角度分析Android的消息机制系列——Handler的工作原理
Posted 琳茹的技术轮子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原创源码角度分析Android的消息机制系列——Handler的工作原理相关的知识,希望对你有一定的参考价值。
ι 版权声明:本文为博主原创文章,未经博主允许不得转载。
先看Handler的定义:
/** * A Handler allows you to send and process {@link Message} and Runnable * objects associated with a thread‘s {@link MessageQueue}. Each Handler * instance is associated with a single thread and that thread‘s message * queue. When you create a new Handler, it is bound to the thread / * message queue of the thread that is creating it -- from that point on, * it will deliver messages and runnables to that message queue and execute * them as they come out of the message queue. * * <p>There are two main uses for a Handler: (1) to schedule messages and * runnables to be executed as some point in the future; and (2) to enqueue * an action to be performed on a different thread than your own. * ………. * */ public class Handler { …….. }
由源码中对Handler的定义以及注释,我们可知,Handler主要就是用来发送和处理消息的。每一个Handler的实例都和一个线程以及该线程的MessageQueue相关联。Hadnler主要有2个作用:①在未来某个时刻去发送或处理Message或Runnable(post方法)②在另一个线程中去处理消息(send方法)。
再看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) { throw new RuntimeException( "Can‘t create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; } ……
由构造方法可知,当前线程中没有Looper时,若创建Handler对象,则会抛出"Can‘t create handler inside thread that has not called Looper.prepare()"异常。所以,必须要在有Looper的线程中创建Handler,否则,程序将抛出异常。
Handler的工作主要包含消息的发送和接收过程。消息的发送可以通过post的一系列方法以及send的一系列方法来实现。下面来看一系列post方法:
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)); }
通过源码,我们可以知道,post的一系列方法最终还是通过send的一系列方法来实现的。
下面看send的一系列发送消息的源码:
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } public final boolean sendEmptyMessage(int what) { return sendEmptyMessageDelayed(what, 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); }
由源码可知,Handler发送消息的过程,其实就是向消息队列中插入了一条消息。
由MessageQueue的工作原理和Looper的工作原理我们可以知道,当MessageQueue中插入了新的消息后,next方法就会返回该消息给Looper,Looper接收到消息并开始处理消息,但最终Looper是通过调用Handler的dispatchMessage方法来处理消息的,即消息最终还是交给了Handler去处理。
下面来看Handler的dispatchMessage方法的源码,如下:
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } private static void handleCallback(Message message) { message.callback.run(); }
首先,判断了Message的callback是否为null,若不为null,则调用handleCallback方法。
Message中有属性: /*package*/ Runnable callback; 那么,message.callback即Handler的post方法所传递的Runnable参数。再结合handleCallback方法的源码可知,handleCallback方法其实就是开启了一个子线程,去处理post方法。
再看dispatchMessage方法的源码,若Message的callback为空,则判断mCallback是否为null,由Handler的源码:
final Callback mCallback; public interface Callback { public boolean handleMessage(Message msg); } /** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { }
可知,Callback就是一个接口,而且其中定义了handleMessage方法。由此我们可以联想到,当需要获取一个Handler实例时,我们除了可以继承Handler,重写handleMessage方法外,我们还可以通过实现Callback 接口,然后实现接口中的handleMessage方法来实现。
接着来看dispatchMessage方法的源码,若mCallback为null,最后还是调用handleMessage方法来处理消息。
在开发过程中,当用Handler处理消息时,我们一般是需要重写handleMessage方法的,处理消息的逻辑由我们自己来写。
以上是关于原创源码角度分析Android的消息机制系列——Handler的工作原理的主要内容,如果未能解决你的问题,请参考以下文章
原创源码角度分析Android的消息机制系列——Handler的工作原理
原创源码角度分析Android的消息机制系列——ThreadLocal的工作原理
原创源码角度分析Android的消息机制系列——MessageQueue的工作原理
原创源码角度分析Android的消息机制系列——ThreadLocal的工作过程