Handler创建时如果没有给定Looper,那他会与主线程的Looper相关联,也就是默认运行在主线程中,在主线程中可以进行UI更新操作。但是如果Handler处理的内容不涉及UI更新等,同时又是一个非常耗时的操作, 那就会造成阻塞,我们有必要将这些操作在子线程中运行。android提供了HandlerThread方便了这个过程,官方文档对这个类的描述:
Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.
HandlerThread继承Thread,它其实就是一个Thread,只是封装了一个Looper,这个Looper和一个子线程相关联。
现在分析一下代码:
使用HandlerThread时必须先要调用start()方法,随后就会调用run()方法,查看HandlerThread.run()方法代码:
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
上面代码中,Looper.prepare()方法创建了Looper,查看Looper的创建代码:
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
这里创建了Looper并且当前Looper和当前的线程相关联,也就是说该Looper不在主线程中。我们可以通过HandlerThread.getLooper() 方法获取Looper对象。
现在回到run()方法,有一个onLooperPrepared()方法,这是一个空方法,我们可以重写该方法。run()方法中随后Looper开启消息循环
现在看一下下面的代码:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final int UPDATE_UI = 1;
private MyHandler mMyHandler;
private HandlerThread mHandlerThread;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMyHandler = new MyHandler();
changeView();
Log.i(TAG, "now thread = " + Thread.currentThread());
}
private void changeView() {
new Thread(new Runnable() {
@Override
public void run() {
Message message = Message.obtain(mMyHandler);
message.obj = 1;
message.sendToTarget();
Log.i(TAG, "now thread = " + Thread.currentThread());
}
}).start();
}
private class MyHandler extends Handler {
public MyHandler() {
super();
}
public MyHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
Log.i(TAG, "now thread = " + Thread.currentThread());
}
}
}
在onCreate()、子线程、和mMyhandler中打印运行的线程,看一下效果:
可以看到默认创建的Handler的handleMessage()方法在主线程中运行。 现在借助HandlerThread创建Handler:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final int UPDATE_UI = 1;
private MyHandler mMyHandler;
private HandlerThread mHandlerThread;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandlerThread = new HandlerThread("handler thread");
mHandlerThread.start();
mMyHandler = new MyHandler(
mHandlerThread.getLooper());
changeView();
Log.i(TAG, "now thread = " + Thread.currentThread());
}
private void changeView() {
new Thread(new Runnable() {
@Override
public void run() {
Message message = Message.obtain(mMyHandler);
message.obj = 1;
message.sendToTarget();
Log.i(TAG, "now thread = " + Thread.currentThread());
}
}).start();
}
private class MyHandler extends Handler {
public MyHandler() {
super();
}
public MyHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
Log.i(TAG, "now thread = " + Thread.currentThread());
}
}
}
打印日志:
可以看到创建Handler时制定了Looper,此时Handler的handleMessage()方法在Looper所在的线程运行,而不是在主线程中。
通过上面的分析和例子,应该可以理解HandlerThread的作用和用法了。