大家都明白UI的更新只能在UI主线程,如果要在子线程更新UI就好抛出异常提示,自己的view自己修改,别人别管那么多。之所以UI是由单线程控制是为了避免多线程带来无法预期的“错误”。既然这样干嘛不加个锁同步一下,很简单因为影响性能,会带来不友好的用户体验。所以这条路也行不通,就出现了handler这种消息机制来解决上面问题。
一、核心对象
在handler机制中有三个类,分别是handler、looper、message,当然还有一个很关键的MessageQueue(消息队列,后面简称mq)已经封装到looper中。
handler:负责发送message到mq中,然后从mq中获取message,并做相应处理;
looper:内置mq存放handler发送过来的message,指定message给对应的handler处理;
message:消息,可以封装一些数据,handler会根据不同的message作出不同的处理;
二、使用
通常在使用中会发现根本用不到looper类,mq也没出现过,那是因为在Activity中会自动启动一个looper对象。如果是用户自定义的类就需要手动去启动looper对象
启动方法:
创建一个线程类并把它变成looper线程
一个线程要变成looper线程很简单只需两行核心代码
public class LooperThread extends Thread {
@Override
public void run() {
// 将当前线程初始化为Looper线程
Looper.prepare();
// ...其他处理,如实例化handler
// 开始循环处理消息队列
Looper.loop();
}
}
变成looper线程就是调用perpare和loop两个方法,方法作用已经注释,至于具体的实现过程可以参考源码。
当然looper还有其他好用的方法例如
myLooper:获取当前线程looper对象(一个线程只能有一个looper对象)
getThread:获取looper对象所属线程
quit:结束looper循环
虽然looper及其方法一般不常用,但我们还是要知道looper在整个消息机制中是充当一个通道的角色,handler发送消息通过looper到mq中,mq中的消息通过looper又重新分配的handler中。
handler用法很简单,就是在子线程通过handler对象引用调用发送消息的方法,然后在主线程中的handler中接收消息
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what==110&&isPause==false){
for(int i=0;i<names.length;i++){
views[i].setBackgroundResource(colors[(i+changeColor)%colors.length]);
}
changeColor++;
}
super.handleMessage(msg);
}
};
Timer timer=new Timer();
//设置timer
public void setTimer(){
isPause=false;
TimerTask timerTask=new TimerTask() {
@Override
public void run() {
handler.sendEmptyMessage(110);
}
};
timer.schedule(timerTask,0,500);
}
上面代码使用了一个定时任务,定时任务需要创建子线程来处理任务逻辑,处理完逻辑就发送消息让UI更新一下
当然上面发送的是一个message为空的消息,我们的message也可以不为空,直接new一个对象即可,不过建议使用obtain的方法从消息池中获取对象。message还有以下成员:
int what:变量,用于定义此Message属于何种操作
Object obj:变量,用于定义此Message传递的信息数据,通过它传递信息
int arg1:变量,传递一些整型数据时使用
int arg2:变量,传递一些整型数据时使用
Handler getTarget():普通方法,取得操作此消息的Handler对象。
使用建议就是尽量使用what标识message,传递数据如果是整型的话就尽量使用 arg1、arg2;
三、总结
消息机制的使用是为了让子线程能够更新UI界面(或者叫间接更新比较合理),不过在Activity中还可以在子线程调用runOnUIThread方法来达到目的。关于handler机制基本参考 以下地址,有空可以去看看,虽然附带源码解析,不过通俗易懂。
https://my.oschina.net/u/1391648/blog/282892