关于Android中的Handler,其实并不陌生。初入Android时写网络模块的时候,经常会用到,因为Android中3.0版本之后是不应许在主线程中直接调起网络请求,所以只有在子线程中开启网络请求。而Android中不应许在子线程中操作UI,所以要界面响应网络请求的结果,就需要通过Handler来刷新UI。后来网络请求框架如雨后春笋般崛起,自己再去通过Handler来刷新界面就用的少了。再后来用的多的地方是使用Handler的延时效果。
用途
预处理(将来的某个时间点上要做)
线程间通信(异步)
理由
为什么在子线程中发送一个消息,主线程就能收到呢,或者说Handler是怎实现线程间是怎么通信的?
这里需要明白Android是消息驱动型系统(于Windows一样),消息驱动系统的四要素:
- 接受消息的”消息队列”
- 阻塞式地从消息队列中接收消息并进行处理的“线程”
- 可发送的消息格式
- 消息发送函数
在Android中表现为: - MessageQueue
- Thread+Looper
- Message
- Hander的post与sendMessage函数
Handler发送一个消息到MessageQueue处。Looper相当于线程的消息管家,不断的在MessageQueue中读取消息,将消息分发给Handler处理,从而就实现的线程间的通信。
盗一张别人的原理图:
所以实现线程间通信,光有Handler是不够的,你得有配套的机制。而线程默认是没有Looper的,你得使用Looper.perpare()
创建Looper,然后创建Handler,让管家管理消息即Looper.loop()
。大致思路是这样:
- 判定是否已有Looper并Looper.prepare()
- 做一些准备工作(如暴露handler等)
- 调用Looper.loop(),线程进入阻塞态
比如这样:
1 | class LooperThread extends Thread { |
那么如果有人问你,Thread,Looper,MessageQueue,Handler数量关系是怎么样的。你可以这样告诉他。一个Thread最多只拥有一个Looper,一个Thread却是可以有多个Handler。
那么怎么理解Handler的异步或者说异步通信呢?我在主线程里面要网络数据,但是我是莫法在主线程里面直接访问网络的,所以我叫子线程去访问网络,子线程要把网络请求的结果告诉主线程,这个告诉就是回调,就是响应,通过Handler来完成。从而体现了异步。参考
Handler引起的内存泄漏
这里主要明白非静态内部类会持有外部类的引用。
所以在申明Handler的时候不要申明成static的,如果非要申明为static的就要一层如引用包裹Handler。
在onDestroy的时候移除所以的消息和回调removeCallbacksAndMessages(null)