handler机制
简单总结下, handler机制提供了跨线程之前的通信方式。
先来看一段简单的代码示例,线程A创建handler对象,调用looper.prepare(), 创建Looper对象, 和MessageQueue,绑定到当前线程。然后启动looper轮询,sendMessageDelayed()会将Message 加入MessageQueue,然后线程B处理Message
可以发送message给到创建Handler的那个线程,最终由他handlerMessage。
class LoopThread extends Thread {
public Handler mHandler = null;
public LoopThread(String threadName) {
super(threadName);
}
@Override
public void run() {
Looper.prepare();
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case RESPONSE:
System.out.println("接受到[" + Thread.currentThread().getName() + "]发送的消息");
break;
default:
break;
}
}
};
Looper.loop();
}
}
//threadB处理消息
final LoopThread threadB = new LoopThread("ThreadB");
threadB.start();
//threadA发送消息
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
Message msg = new Message();
msg.what = RESPONSE;
threadB.mHandler.sendMessage(msg);
System.out.println("["+Thread.currentThread().getName() + "]发送消息");
}
}, "ThreadA");
threadA.start();
接下来分析下handler的源码,省略无用方法, 讲解主要的方法,以此来理解handler的机制。
handler sendMessage() 将消息加入message队列
//handler.post()
//调用sendMessageDelayed, 最终调用enqueueMessage
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
//Message.obtain() 利用对象池的方式获得Message 对象, 并且将Runnable 设置为Message对象的callback
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
//将msg 加入到MessageQueue
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//msg.target 保持当前handler对象的引用
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
looper 循环处理消息队列
主线程默认就会调用如下两个方法。如果在子线程使用handler就要在前后加入这两个方法,这样就会在子线程中轮询MeesageQueue了。
looper.prepare()
创建Looper对象, 创建MessageQueue, 并且Looper持有MessageQueue的引用,当前线程持有Looper对象引用
//创建一个looper对象, 并且设置为ThreadLocal
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//这里会把new 出来的Looper对象保存到当前线程中
sThreadLocal.set(new Looper(quitAllowed));
}
//new Looper() 创建MessageQueue, 并且保留当前线程
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
looper.loop()
遍历MeesageQueue, 调用handler的 dispatchMessage()处理Message
//开始循环处理meesageQueue
public static void loop() {
//首先获取ThreadLocal的Looper对象
final Looper me = myLooper();
//获取Looper对象引用的MeesageQueue
final MessageQueue queue = me.mQueue;
//无限循环
for (;;) {
//有消息取, 否则阻塞
Message msg = queue.next(); // might block
if (msg == null) {
return;
}
//调用Message对象引用的handler对象的dispatchMessage()分发消息
msg.target.dispatchMessage(msg);
}
}
handler处理Message
这里如果msg 有callback则先执行msg的callback;
否则执行handler的callback的handleMessage;
否则执行handler子类的handleMessage;
public void dispatchMessage(Message msg) {
//如果Message的回调不为空, 则回调callback
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//处理Message
handleMessage(msg);
}
}
private static void handleCallback(Message message) {
message.callback.run();
}
//handlerMessage为空, 由子类去实现
public void handleMessage(Message msg) {
}
主线程默认就有一个Looper对象, 在ActivityThread
public static void main(String[] args) {
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
}
handler构造方法
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();
//这里如果在子线程使用handler 不调用looper.prepare(), 则会报如下错误。这个应该很多人遇到过吧?
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;
}
HandlerThread
主要作用是很简单的创建一个带looper的线程,方便的使用handler的机制做异步处理。
但是他只有一个线程,适合串行任务,不适合做并行任务。比如网络IO阻塞时间比较长的,推荐使用线程池或者asyncTask+线程池来处理。
源码:
public class HandlerThread extends Thread {
public HandlerThread(String name, int priority) {
super(name);
//可以设置线程优先级,因为默认的优先级是比较高的,所以可以设置低一点
mPriority = priority;
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
示例:
HandlerThread workerThread = new HandlerThread("workerThread", Process.THREAD_PRIORITY_BACKGROUND);
workerThread.start();
mHandler = new Handler(workerThread.getLooper());