首先,我们平时直接创建的Handler实例默认是在主线程,是可以直接更新UI操作,而在子线程创建的Handler则不可以直接更新UI操作(可以通过runUIThread(Runnable run)切换到主线程),下面介绍两种在子线程创建Handler的方式:
一、基本方式
private Handler mHandler;
//创建子线程handler
private void createHandler(){
new Thread(new Runnable() {
@Override public void run() {
//当前子线程创建looper
Looper.prepare();
//传入子线程Looper,也可以不传,默认也为该线程looper
mHandler = new Handler(Looper.myLooper());
//启动looper
Looper.loop();
}
}).start();
}
//推送任务到消息队列
private void postRun(){
mHandler.post(new Runnable() {
@Override public void run() {
//执行耗时操作
SystemClock.sleep(5000);
//更新UI
MainActivity.this.runOnUiThread(new Runnable() {
@Override public void run() {
actTextReslt.setText("完成操作");
}
});
}
});
}
注:Looper.prepare()--》new Handler()--》Looper.loop()要按此顺序执行,由于子线程默认没有Looper而handler工作需要looper对象,直接创建handler对象会报java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
二、HandlerThread方式(HandlerThread内部创建消息队列,外部通过handler通知HandlerThread执行)
private Handler mHandler;
//创建子线程handler
private void createHandler(){
HandlerThread handlerThread = new HandlerThread("myHandlerThread", Process.THREAD_PRIORITY_BACKGROUND);
handlerThread.start();//必须开启
mHandler = new Handler(handlerThread.getLooper());
}
//推送任务到消息队列
private void postRun(){
mHandler.post(new Runnable() {
@Override public void run() {
//执行耗时操作
SystemClock.sleep(5000);
//更新UI
MainActivity.this.runOnUiThread(new Runnable() {
@Override public void run() {
actTextReslt.setText("完成操作");
}
});
}
});
}
三、子线程中创建主线程handler
new Thread(() -> {
Handler handler = new Handler(Application.getContext().getMainLooper());
}).start();
总结:
(1)方式二是Android对方式一的封装,使用起来更简单。其中HandlerThread构造方法的第二个参数表示优先级(范围-20~19,越小优先级越高)
(2)handler消息队列是串行的(即处理完当前消息,才进行处理下一个消息),背后只有一个线程,这里区别于线程池,对于并行需求考虑线程池解决