一般我们使用Hanlder
是在子线程和UI线程(主线程)之间传递消息,当Hanlder
在UI线程中new出来时候,如果没有显示指定looper的话,会自动绑定当前所在线程即UI线程的Looper,looper管理了一个MessageQueue。其他子线程就可以通过持有该Hanlder
的引用,传递消息message,message被放到MessageQueue里面,并被相应handler所绑定线程的looper取出来,在handler的handleMessage()方法里执行相应的处理。handleMessage()所执行的线程就是handler绑定的looper所在的线程。
UI线程创建时候会自动初始化looper的相关操作,而为子线程创建对应handler则必须手动执行这些步骤。如下:
Handler mHandler;
private void createManualThreadWithHandler() {
new Thread() {
@Override
public void run() {
super.run();
Looper.prepare();//生成looper
mHandler = new Handler(Looper.myLooper()) {//显式持有子线程的looper
@Override
public void handleMessage(Message msg) {
//实际的耗时处理任务,在子线程中运行
};
Looper.loop();//不断查询是否有消息进来,此处是死循环
}
}.start();
}
子线程收到消息后实际任务处理在handleMessage中执行。
HandlerThread实际就是一个Thread,为了方便我们为其创建handler,就在run方法里做了Looper的相应初始化操作,源码如下:
//调用 start() 后就会执行的 run()
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare(); //帮我们创建了 Looepr
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll(); //Looper 已经创建,唤醒阻塞在获取 Looper 的线程
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop(); //开始循环
mTid = -1;
}
对HandlerThread我们就可以这样为其创建handler,省去了looper的准备工作:
HandlerThread handlerThread = new HandlerThread("name");
handlerThread.start();
Handler threadHanler = new Handler(handlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//do something
//此处代码实际运行在子线程:handlerThread
}
};
当然,也可以通过在重新的onLooperPrepared()方法来创建handler:
class MyHandlerThread extends HandlerThread {
Handler mHandlerThreadHandler;
public MyHandlerThread(String name) {
super(name);
}
@Override
protected void onLooperPrepared() {
super.onLooperPrepared();
mHandlerThreadHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
SystemClock.sleep(2000);//模拟耗时操作
Toast.makeText(MainActivity.this, "handlerThread:" + msg.obj, Toast.LENGTH_SHORT).show();
super.handleMessage(msg);
}
};
}
}
参考:
http://blog.csdn.net/u011240877/article/details/72905631
http://droidyue.com/blog/2015/11/08/make-use-of-handlerthread/index.html