Handler是一个Android SDK 提供给开发者方便进行异步消息处理的类。来看handler的基本实现
//模拟子线程
new Thread(new Runnable() {
@Override
public void run() {
//模拟在线程中新建Message 兑现,Message.obtain()是Message中的方法,用来从缓冲中获取
Message message = Message.obtain();
message.obj = "测试";
//发送一个消息
sHandler.sendMessage(message);
}
}).start();
@SuppressLint("HandlerLeak")
private static Handler sHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//在这里可以获取线程中的消息,而且该方法是在主线程中
Log.e("TAG", "" + msg.obj);
}
};
我们先来看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 赋值到Message中,类似绑定
//注意当前的handler 是在main线程中初始化的
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
最终调用的是MessageQueue 的enqueueMessage()方法,继续点进来看看
boolean enqueueMessage(Message msg, long when) {
//判断 Message 中是否有 target 也就是是否有 handler
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
//判断该 Message 是否已经在使用
//所以如果连续调用两次 sHandler.sendMessage(message); 就会抛这个异常
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
//判断是否弃用,如果弃用直接返回
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
//标记正在使用中
msg.markInUse();
//将 when 的值赋给 msg
msg.when = when;
Message p = mMessages;
boolean needWake;
//下面这一段代码我做了一些删减,只留下重要部分
//这段代码的作用就是,将 sendMessage 过来的 message 按照 when 的大小,用链表的形式保存
//实在没法理解 可以去看看这篇文章 https://www.jianshu.com/p/b1169f85501c
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
} else {
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
}
msg.next = p;
prev.next = msg;
}
}
return true;
}
到这里 sHandler.sendMessage(message); 就已经完了,至于什么时候会回调 handleMessage 方法?下面来介绍两个方法
//相当于初始化方法
Looper.prepare();
//轮循
Looper.loop();
点进去看看Looper.prepare();
//使用ThreadLocal 确保线程安全
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
//使用 ThreadLocal 来确保一个线程只存在一个Looper对象
//关于 ThreadLocal 如何确保一个线程只存在一个对象,请自行了解
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
//创建MessageQueue队列
mQueue = new MessageQueue(quitAllowed);
//获取但前线程
mThread = Thread.currentThread();
}
从上面可以知道Looper.prepare();方法就是new 一个Looper对象,在Looper中new MessageQueue对象,实现Looper 和MessageQueue的绑定
再看Looper.loop();方法
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
public static void loop() {
//获取但前线程的looper对象
final Looper me = myLooper();
//如果为null 直接抛异常,
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//获取Looper 中的MessageQueue
//前面可以知道 new Looper 的时候 new MessageQueue
final MessageQueue queue = me.mQueue;
//死循环不断获取消息进行处理
for (;;) {
//获取MessageQueue 中的Message,下面在分析next()方法
Message msg = queue.next();
if (msg == null) {
// 没有消息返回
return;
}
//.......
try {
//注意看,这里的target 就是handler 对象,直接调用dispatchMessage()方法
//target 在 sendMessage 的时候赋值
msg.target.dispatchMessage(msg);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
//.......
//这个消息处理完毕,释放资源
msg.recycleUnchecked();
}
}
我们先来分析next()方法
Message next() {
//又是一个循环
for (;;) {
synchronized (this) {
//获取时间
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
//同步屏障
if (msg != null && msg.target == null) {
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
//判断当前时间和msg的时间比较,是否需要处理
if (now < msg.when) {
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// 获取需要处理的msg
//也是链表,将头节点的值设置为next节点的值,
//将之前的头节点的next 置null 并返回
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
//标记正在使用
msg.markInUse();
return msg;
}
} else {
// 没有消息
nextPollTimeoutMillis = -1;
}
省略代码.......
next()方法就是不断循环MessageQueue 获取到Message 对象
我们再来分析msg.target.dispatchMessage(msg);
public void dispatchMessage(Message msg) {
//判断是否传了 callback ,其实就是Runnable
//如果传了就直接调用 run 方法,
//没有就调用 handleMessage 就是我们new handler 时重写的方法
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
//直接调用run 方法
private static void handleCallback(Message message) {
message.callback.run();
}
//什么都没有传的时候,直接调用handleMessage()方法,就是调用我们重写的方法
public void handleMessage(Message msg) {
}
到这里就结束了,handler 的整套流程。至于为什会有后面的两个方法,我们在主线程中也没有调用这两个方法,为什么就能直接使用,这就需要来看activity 的启动流程,我们来简单看下ActivityThread 中的main 方法
public static void main(String[] args) {
//系统已经帮我们出事后了
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//调用loop
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
public static void prepareMainLooper() {
//最后还是会调用prepare 方法
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
最后再介绍一种情况,当直接在子线程中new Handler会发生什么呢?
new Thread(new Runnable() {
@Override
public void run() {
Handler handler = new Handler();
}
}).start();
会直接抛异常
进去看看 new Handler(); 做了什么
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
//前面已经介绍了,这个方法就是使用 ThreadLocal 获取当前线程的looper对象
mLooper = Looper.myLooper();
//获取不到,抛出异常,这就是前面异常的原因
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
所以我们需要在子线程中new Handler(); 需要加入looper 初始化操作
new Thread(new Runnable() {
@Override
public void run() {
//初始化当前线程的looper 对象
Looper.prepare();
Handler handler = new Handler();
//轮询
Looper.loop();
}
}).start();
好了,到这里就结束了handler 之旅了。