1、Handler的诞生背景
在Android中,规定了只能在主线程(或者叫UI线程)中,去进行UI相关的操作,而其他线程则无法操作UI,否则报错;
但同时,由于不能再UI线程进行耗时的操作,否则会报ANR异常, 因此,我们通常又把耗时操作放到子线程去进行一个处理。
那这就涉及到了一个数据传递的问题,我们在子线程处理的数据,怎么传递到主线程呢?这就有了Handler消息机制。
2、Handler、MessageQueue、Looper的作用简介
我们可以通过Handler对象发送消息到主线程进行处理。 至于为什么通过handler就可在主线程处理,原因及源码的分析见下一篇Android消息机制详解,这里先简单做一个介绍。
Handler消息机制主要由Handler、MessageQueue、Looper三个部分组成。通过Handler发送消息到主线程的MessageQueue这个消息队列进行存储,其中MessageQueue是一个单链表结构,然后由Looper轮询器依次从MessageQueue取出数据,在主线程进行处理,其中Looper是一个死循环。
3、用Handler处理耗时操作
Handler最常见的用法就是处理耗时任务,此种情况通常报随着子线程,通常是在子线程把耗时任务处理完以后,再通过Handler回调到主线程进行处理:
public class HandlerTestActivity extends Activity {
private static Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
//此方法处理handler对象在其他位置或线程发送过来的消息
//此方法是在主线程被中调用,
switch (msg.arg1) {
case 1:
//此处做逻辑处理,如更新UI
default:
}
}
};
private void dealLongTimeTask() {
//新开线程
new Thread(){
@Override
public void run() {
super.run();
//在这个子线程先执行耗时操作,然后通过handler将执行完的数据传递到主线程
Message msg = Message.obtain();
//msg提供了一些属性和方法来传递数据,可以根据自己的需求选择其中一些来传值;
msg.arg1 = 1;//随便设置几个值
msg.arg2 = 2;
msg.obj = new String("test");
mHandler.sendMessage(msg);
}
}.start();
}
...
}
4、用Handler.postDelayed处理定时任务
可以直接使用postDelayed将我们的任务延时处理,但是在run方法中也不能继续耗时操作,因为run方法也是运行在主线程的,只要有耗时操作,都应该在子线程处理,处理完得到数据后,再通过handler或者接口回调等,把数据传递给主线程处理;
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
//此处执行我们的任务, 但是不建议执行耗时任务
//因为run方法在主线程被执行;
//可以把耗时操作得到的数据,在此处进行处理
}
}, 1000);
5、用Handler.post处理普通任务
使用Handler.post方法,run方法会直接在主线程进行执行。
mHandler.post(new Runnable() {
@Override
public void run() {
//此处执行我们的任务, 但是不建议执行耗时任务
//因为run方法在主线程被执行;
//可以把耗时操作得到的数据,在此处进行处理
}
});