一,作用:是用来做异步的,用于在子线程更新UI
二,关键类的详细介绍
1,概念介绍
Message
· 定义:消息,理解为线程间通讯的数据单元(Handler接受和处理的消息对象。)
例如后台线程在处理数据完毕后需要更新UI,则可发送一条包含更新信息的Message给UI线程
Message Queue
· 定义:消息队列
· 作用:用来存放通过Handler发过来的消息,按照先进先出执行
Handler
· 定义:Handler是Message的主要处理
.作用:负责将Message添加到消息队列&处理Looper分派过来的Message
Looper
定义:循环器,扮演Message Queue和Handler之间桥梁的角色
作用:主要负责消息循环:循环取出Message Queue的Message;消息派发:将取出的Message交付给相应的Handler
一个线程只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue
2,相关方法介绍
Handler
· 提供sendMessage方法,将消息放置到队列中
· 提供handleMessage方法,定义个各种消息的处理方式;
Looper
· Looper.prepare():实例化Looper对象;为当前线程生成一个消息队列;
· Looper.loop() :循环从消息队列中获取消息,交给Handler处理;此时线程处于无限循环中,不停的从MessageQueue中获取Message 消息 ;如果没有消息就阻塞
MessageQueue
· 提供enqueueMessage 方法,将消息根据时间放置到队列中;
· 提供next方法,从队列中获取消息,没有消息的时候阻塞;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
Log.e("date","接收到传递的信息了" );
break;
}
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
Message msg = Message.obtain();
msg.what = 1;
mHandler.sendMessage(msg);
}
}).start();
}
三,实现原理:
每当创建一个handler的时候,就会创建一个MessageQueue来存储消息,接着创建Lopper循环器,在Messagequeue队列里不停的轮训,看看有没有消息,没有消息就一直轮训,当Handler拿到消息,就会通过sendMessage()方法,将message从子线程发送出去,这个时候looper轮训到有消息来,就会将传递出去,传递到handler的handlerMessage()方法中,这个时候就可以在UI线程刷新数据了.
这个MessageQueue队列的结构其实并不是队列,而是采用单链表的数据结构来维护消息队列,因为单链表的数据结构在插入和删除上比较有优势.
Handler一般只能只在主线程创建对象,如果在子线程创建对象,会报错,(has not called Looper.prepare())因为Handler工作需要Looper,没有lopper就会报错.在主线程内部自带的调用了Lopper.prepare()方法创建Lopper对象.如果想要在子线程创建对象,就必须自己调用prepare()方法,如果想在子线程接收消息,还得调用Looper.loop()方法不停轮询,才能收到消息.但在事情结束后,要调用quit()来终止消息循环,否则线程就会处于一直等到状态
3,其他重要的类:
ThreadLocal,它是一个可以在指定线程中存储数据的类,数据存储以后,只有在指定的线程中可以获取到存储的数据,在其他线程无法获取该数据,ActivityThread,ActivityManagerService就用到了就用到了ThreadLocal.
4,不同线程有不同的lopper
四,源码
1,自身的创建&创建Message Queue:prepare()方法
五,Handler造成的内存泄漏,
1,handler造成内存泄漏是因为在Activity销毁的时候还有未执行完的任务
2,解决方法:
2.1,静态static可以解决内存泄漏
2.2,使用弱引用也可以解决内存泄漏,但是需要等到handler的中任务都执行完,才会释放activity内存,不如直接static释放的快
2.3, handler.removeCallbacksAndMessages(null);
3,handler造成内存泄漏有 两种方案:一种是业务逻辑上,在activity销毁的时候移除所有未执行的任务。一种是从GC上,通过static的Handler或者弱引用解决。但是单独的使用弱引用性能不是太高。
借鉴: