我们知道在Android中的UI线程中请求网络,需要开启子线程进行请求网络。但是,子线程中的网络请求结束之后需要更新UI,此时就比较头疼了,这时,Handler的出现就能解决此问题。
那么问题来了,什么是Handler以及原理又是怎样的呢?
什么是Handler?
Handler是用于在2个线程之间进行通信的一个工具。比如:在UI线程中创建一个Handler对象,然后再子线程中调用Handler对象的sendMessage方法,可以将数据从子线程传递到UI线程,最后将数据显示到View中。
简单说:Handler就是一个在线程间发送消息的工具。 相当于手机
Handler的基本使用
发送消息 | |
---|---|
sendMessage | 发送消息 |
sendMessageAtTime | 在制定时间发送一个消息,时间是以开机时间作为基准,在此基准上,可以加上制定的毫秒数。需要使用SystemLock.upTImeMillis() |
sendMessageDelayed | 延迟发送消息 |
sendEmptyMessage | 发送一个空消息 |
sendEmptyMessageAtTime | 指定时间发送空消息 |
sendEmptyMessageDelayed | 延迟发送空消息 |
Handler的传递机制:
主要的类有:Handler、Message、MessageQueue、Looper
子线程中创建Handler方式和注意事项
解决:
Looper.prepare()
不要忘记Looper.loop方法
步骤:
1、执行Looper.prepare()
2、创建Handler
3、sendMessage
3、Looper.loop()
注意:
在子线程中创建的Handler,其handleMessage方法执行在子线程中。
在主线程中创建的Handler,其handleMessage方法执行在主线程中。
以上2条结论取决于Looper是在主线程还是子线程。
如果是在子线程创建的Handler,但是Looper是主线程的Looper,则Handler还是执行在主线程中,反之亦然。
new Thread(new Runnable() {
private MyHandler myHandler;
@Override
public void run() {
//在子线程中创建Handler之前,需要执行Looper.Prepare方法
Looper.prepare();
//创建Handler
myHandler = new MyHandler();
myHandler.sendEmptyMessage(1);
Looper.loop();
}
class MyHandler extends Handler {
// public MyHandler(Looper looper) {
// super(looper);
// }
@Override
public void handleMessage(Message msg) {
Log.d("androidxx", "handleMessage: " + Thread.currentThread().getName());
}
}
}).start();
Handler内存溢出
解决:
按照如下创建Handler:使用static Handler,并且弱引用Activity,可以避免内存溢出。
static class MyHandler extends Handler {
private WeakReference<MainActivity> activityWeakReference;
// public MyHandler() {
// }
public MyHandler(MainActivity mainActivity) {
// this.mainActivity = mainActivity;
activityWeakReference = new WeakReference<MainActivity>(mainActivity);
}
/**
* 接收消息
* @param msg 接收到的消息,sendMessage发送
*/
@Override
public void handleMessage(Message msg) {
Log.d(TAG, "handleMessage: " + msg.obj);
if (activityWeakReference.get() != null) {
activityWeakReference.get().mShowTxt.setText(msg.obj.toString());
}
}
}
总结:
Handler是负责发送和接收消息的
Message是用来做消息封装的
MessageQueue是一个消息队列,用来存放Message对象,它是交由Looper来进行管理,而MessageQueue里面的Message循环调用,是采用Looper里面的loop方法。
首先,Handler通过sendMessage方法发送一个Message对象,然后这个Message对象会进入到MessageQueue里面。其次,Message对象是由Looper对象来管理的,而Looper里面有个loop方法来循环MessageQueue里面的Message,当Message遍历出来之后就可以通过Message里面的target可以调用到HandlerMessage方法。