一,概述
Android中为什么需要Handler机制?因为在android中有两个规定:
1. 网络请求操作要放到子线程。
2. 不能在子线程更新UI。
所以Android中必须有线程间的通讯机制,Handler的作用就是负责线程间的通信。在网络请求完成后,通过handler告诉UI线程更新UI,并传递数据。
二,使用示例
1,在成员变量位置创建Handler对象,并重写handleMessage方法:
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {//方法执行在UI线程
super.handleMessage(msg);
if(msg.what == 1) {
String message = (String) msg.obj;
Toast.makeText(this,"请求成功",Toast.LENGTH_SHORT).show();
}
}
};
2,在网络请求完成后调用handler的sendMessage方法
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);//模拟网络请求
} catch (InterruptedException e) {
e.printStackTrace();
}
//网络请求完成后做下面操作
Message message = Message.obtain();
message.obj = "这是来自子线程的HandleMessage消息";//message携带的数据
message.arg1 = 10;//若果仅仅传递一个整数,可以使用arg1
message.what = 1;//此消息的标记,一个handler可能会发送很多消息,使用标记区分
handler.sendMessage(message);
}
}).start();
总结:在子线程中,网络请求完成后调用handler的sendMessage方法,然后handler的handleMessage方法就会执行,这个方法执行在UI线程,所以在这个方法中可以更新UI。这样就实现了线程间数据的传递。
三,Handler发送消息的几个方法
handler发送消息的方法除了sendMessage还有很多,有兴趣的可以查看Handler类的源码,下面说一下几种常用的方法。
1,sendMessage(Message msg)
发送消息,并携带数据,当这个方法执行后handler的handleMessage方法就会执行。
2,sendEmptyMessage(int what)
发送空消息,当不需要携带数据时使用此方法。
3,sendMessageDelayed(Message msg, long delayMillis)
发送延迟消息,当这个方法执行后handler的handleMessage方法不会立即执行,过一段时间才执行。
四,使用Handler的post方法发送消息
在以上的使用中HandlerMessage方法和sendMessage是分开的,即发送消息与功能代码是分开的,这种使用方式有时会很麻烦,此时我们可以使用Handler的post方法代替。post方法的使用示例如下:
Handler handler = new Handler();//在UI线程创建handler对象
new Thread(new Runnable() {
@Override
public void run() {
handler.post(new Runnable() {
@Override
public void run() {//run方法执行在UI线程
//这儿写逻辑代码
}
});
}
}).start();
注:此时的handler对象的创建必须在UI线程,我们可以在Application中创建handler对象,保存成成员变量,然后就可以在任何地方使用,包括在工具类中也可以使用,此时就不依赖于Activity了。
五,在子线程中得到UI线程的handler对象
了解handler机制的小伙伴都知道(不了解的可以看下一篇blog),handler对象是哪个线程的它的post方法参数Runnable的run方法就执行在哪个线程。所以我们要是可以在子线程中得到UI线程的handler对象就可以更方便的实现线程间的通信。示例代码如下:
new Thread(new Runnable() {
@Override
public void run() {
Handler handler = new Handler(Looper.getMainLooper());//得到UI线程中的handler对象
handler.post(new Runnable() {
@Override
public void run() {
//这儿写逻辑代码
}
});
}
}).start();
注:使用这种方法可以轻松的从子线程跳转到UI线程,完全不依赖于Activity或Application。图片加载框架Picasso,网络请求控件Volley都是通过这种方法实现更新UI的。
六,取消handler发送的延迟消息
使用handler可以发送延迟消息,所以可以使用handler做一个定时器实现轮播图,当这个activity不可见或者退出时我们就需要停止轮播图来节约内存,此时就需要使用handler取消消息地方方法,一行代码如下:
handler.removeCallbacksAndMessages(null); //取消所有的回调方法和message