关于Handler的理解
个人对于Handler的理解,用于记录和帮助理解。
Android的消息队列机制中具有三个重要元素,Handler、Looper、MessageQueue。
- Looper中循环取消息并发送消息
- MessageQueue则用来存储消息
- Handler则用来创建消息
Handler
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;}
Lopper
在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
随后我们进入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数据。
更多相关文章
- Android(安卓)数据存储和文件使用案例分析
- ExifInterface使用,Android(安卓)2.0新增类
- android 使用AsyncTask实现异步下载文件
- android通过更改hosts免优酷广告方法
- 如何优雅的避免android(安卓)运行时崩溃
- android 热修复之类加载机制
- Android中Intent概述及使用
- android 跨应用启动/绑定Service && aidl
- Android进阶(一)View体系