(一)创建looper线程的方法比较
在上一篇中,讲到了在UI线程中Handler的原理及使用。如果我们需要在自己的子线程中创建Handler就需要自己为子线程绑定looper了。如下:
private MyHandlerTread mHandlerThread;
mHandlerThread = new MyHandlerTread();
mHandlerThread.start();
class MyHandlerTread extends Thread {
public Handler myHandler;
public void run() {
Looper.prepare();
myHandler = new Handler() {
public void handleMessage(Message msg){
}
};
Looper.loop();
}
}
当然,我们也可以使用简单的方法对上面的方法进行实现,那就是使用HandlerThread。
private HandlerThread myHandlerThread;
myHandlerThread= new HandlerThread("myhandler-thread");
Handler myHandler;
myHandlerThread= new HandlerThread("myhandler-thread");
myHandlerThread.start();
myHandler = new Handler(myHandlerThread.getLooper()) {
public void handleMessage(Message msg){
......
}
};
通过HandlerThread,我们可以更加简单的将子线程变为looper线程。下面来看看HandlerThread是是怎么实现的。
public class HandlerThread extends Thread {
......
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
}
public Looper getLooper() {
if (!isAlive()) {
return null;
}
从上面的源码可以看到,在第6行和13行 同样是执行了looper.prepare()和Loop.looper();在调用new Handler(myHandlerThread.getLooper()) 的时候,实则是调用到了
public Handler(Looper looper) {
this(looper, null, false);
}
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
此处就和之前的方法一样了。
(二)Handler 发送消息的两种方法比较
使用Handler的时候必然会往MessageQueue发送消息。通常的写法如下
(1)
Message msg = new Message();
msg.what = xxx;
msg.ar1 = XXX;
mHandler.sendMessage(msg);
(1)
myHandler.sendMessage(myHandler.obtainMessage(what,arg1,arg2));
这两种方式发送消息由和区别呢?
方法一种可以看到,我们先new 了一个message,然后通过mHandler发送出去。在第二种方法中 myHandler.obtainMessage(what,arg1,arg2)的返回值也是一个message。咋然一看没有什么区别,那我们继续往下看。
public final Message obtainMessage(int what, int arg1, int arg2)
{
return Message.obtain(this, what, arg1, arg2);
}
Message的obtain有多个重载方法,但是最关键的是
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
*/
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
这个方法中,会去从消息池中取出一个消息 进行清空后 返回。如果消息池为空才会去新建一个新的消息对象。因此,在每次通过handler 发送消息的时候,最好使用第二种方法,这样可以减少不必要的内存开销。