个人对于Handler的理解,用于记录和帮助理解。
Android的消息队列机制中具有三个重要元素,Handler、Looper、MessageQueue。
Handler在android用于通信,个人接触到的普遍作用是用于更新UI。因为多线程可能会导出界面更新出错。,所以Android不允许在子线程中进行UI的更新,并给与Hnadler的通信方式。
基本用法很简单
//接收消息
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
text.setText("hello world");
}
};
//发送消息
//发送延时消息
mHandler.sendEmptyMessageDelayed(0,0);
//发送消息的三种方式
mHandler.sendEmptyMessage(0);
mHandler.sendMessage(mHandler.obtainMessage());
mHandler.post(new Runnable() {
@Override
public void run() {
}
});
对于以上三种方式,实现方式一致,只是外在接口形式不同。源码如下:
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);
}
最后都会执行这个方法,所以结合实际情况调用即可。
enqueueMessage方法则消息依次加入MessageQuene中。
post有所不同,内部会加载方法getPostMessage(r)
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
getPostMessage方法内部将r赋值给msg的callback
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
在Handler的构造函数中,初始化变量Looper、MessageQueue。此步骤关联Looper、MessageQueue。
public Handler(Callback callback, boolean async) {
...
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;
}
在myLooper中,拿到Looper
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
Looper不能通过new创建,只能通过peprepare方式创建。
private static void prepare(boolean quitAllowed) {
//通过此判断保证一个线程中只有一个Looper
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
Looper构造函数
private Looper(boolean quitAllowed) {
//因为Looper一个线程只能具有一个,所以一个线程中也只会有一个MessageQueue,并将Looper与当前线程绑定
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
Looper的loop方法用来循环消息队列,取出消息并进行发送
public static void loop() {
//拿到Looper
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;
...
for (;;) {
//取出消息
Message msg = queue.next(); // might block
...
//发送消息
msg.target.dispatchMessage(msg);
...
}
}
通过死循环不停的拿到消息并发送消息。
随后我们进入Message方法中,查找target,发现方法
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;
return m;
}
在Handler最终发送消息的方法中,发现同样代码
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//target指向Handler自己
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
在我们可以通过obtain获取一个复用Message,在此方法中,将target指向了Handler,所以最终会调用Handler的dispatchMessage方法,接着查看Handler的dispatchMessage方法
//我们经常重写的方法
public void handleMessage(Message msg) {
}
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
//检查callback,即post发送消息时赋值的callback
if (msg.callback != null) {
handleCallback(msg);
} else {
//执行过滤器方法,在构造函数中进行初始化
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//在此调用重写的方法
handleMessage(msg);
}
}
//post发送请求方式
private static void handleCallback(Message message) {
message.callback.run();
}
以上,消息发送完全完毕。
为什么Activity中不需要我们进行Looper的创建呢?
因为ActivityThread的main方法中帮助我们进行了Looper的创建。因为Looper的创建过程中绑定了当前线程(主线程),所以Handler可以在UI线程中更新UI数据。