Android消息机制系列(2)——Handler源码解析及用法实例
本文可以和另外一篇文章结合起来看,Android消息机制之——Handler Looper源码分析
在Handler源码开篇,惯例地,有关该类的说明。强烈建议阅读理解10遍+,比任何解说的文章都好用。这里只摘出重要的部分:
* A Handler allows you to send and process Message and Runnable * objects associated with a thread's 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.
1、Handler通过和一个线程的MessageQueue(俗称消息队列)关联,来进行Message、Runnable的发送和处理;
2、每个Handler实例对应唯一的一个线程以及这个线程对应的MessageQueue;依据Handler实例被创建方式的不同,Handler和创建它一个线程或者一个线程的MessageQueue进行绑定;
3、Handler将消息发送到它绑定的MessageQueue; 同时接收从MessageQueue中派发的消息并进行处理。
这里体现出了Handler的主要作用,即将消息切换到绑定的MessageQueue所在的线程里执行,而不管消息是从哪个线程发送过来的。
一、Handler创建方式:
根据是否指定Looper,分为两种:
(1)我们通常使用的方法,直接new Handler的形式;比如,在某个线程中:
class MyThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); //当前线程绑定一个MessageQueue mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); }}
我们知道,Looper.prepare() 是为当前线程绑定一个Looper实例及MessageQueue,在new Handler时,用的就是当前线程的Looper实例和MessageQueue;
Looper的相关细节,可以参见另一篇文章,Android消息机制之——Handler Looper源码分析
调用的构造函数:
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;}
这里面比较核心的两句:
mLooper = Looper.myLooper(); //和当前线程的Looper实例相关联;mQueue = mLooper.mQueue; //和当前线程的Looper实例的MessageQueue相关联。
同时我们发现,构造函数里面是可以指定callback的,这个callback会在处理消息时,也就是dispatch函数里面用到。
而我们通常的做法,在一个Activity的onCreate()函数里面new Handler(),绑定的是主线程的Looper实例和MessageQueue。具体代码可看ActivityThread源代码。
(2) 指定Looper,这是Handler不太常用的,比较特殊的构造方法,通过这种方法,Handler将和指定的Looper以及Looper的MessageQueue进行绑定;
public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async;}
二、Handler两大作用:发送消息 处理消息
发送消息的方法有:
post Runnable方式: post, postAtTime(Runnable, long), postDelayed;
send Message方式: sendEmptyMessage, sendMessage, sendMessageAtTime, sendMessageDelayed;
Runnable对象最终也是被包装成Message对象发送到Handler所绑定的MessageQueue中去:
Runnable 会被包装成设有callback的Message对象:
private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m;}
最终发送消息的方法:
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);}
将消息插入到消息队列中去,并且将消息的target设为本Handler实例(this):
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis);}
我们知道,Handler绑定了一个Looper实例,loop方法会不停地从MessageQueue.next()中看是否有消息,如果有消息,就去调用msg.target.dispatchMessage()进行处理,也就是message对应的Handler实例的dispatchMessage()方法进行处理:
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); // post一个Runnable,Runnable设有callback } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { //构造函数传入callback return; } } handleMessage(msg); // 重写Handler的handleMessage()方法 }}
三、推荐使用obtainMessage方法去获得一个消息对象
我们一般会这样创建一个Message:
Message msg = new Message(); msg.what = xxx; msg.arg1 = xxx; msg.arg2 = xxx; handler.sendMessage(msg);
然而查看源码会发现, obtainMessage方法是获取一个Message对象效率更高的方式:
/*** Returns a new {@link android.os.Message Message} from the global message pool. More efficient than* creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this).* If you don't want that facility, just call Message.obtain() instead.*/
使用obtainMessage()方法,是从全局的MessagePool中去拿一个Message, 而不是重新创建一个,省去了创建对象申请内存的开销。
因此应尽量使用:
Message msg = handler.obtainMessage();
而不要使用:
Message msg = new Message();
参考:
任玉刚 Android开发艺术探索
http://blog.csdn.net/singwhatiwanna/article/details/48350919
更多相关文章
- Android(安卓)ApiDemo学习(三)activity(3)
- Android使用Rotate3dAnimation实现3D旋转动画效果的实例代码
- Android(安卓)AsyncTask 浅析(源代码取自 API level 23)
- Android(安卓)Handler机制5--消息发送
- Android(安卓)碎碎记
- Android(安卓)异步加载图片-AsyncTask
- android 4.0 USB Camera实例(二)应用层
- Android(安卓)UI源码解析
- android ANR相关问题