Better

业精于勤荒于嬉

Android-Handler

Better's Avatar 2017-05-06 Android

  1. 1. 用途
  2. 2. 理由
  3. 3. Handler引起的内存泄漏
  4. 4. 参考

关于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()。大致思路是这样:
  1. 判定是否已有Looper并Looper.prepare()
  2. 做一些准备工作(如暴露handler等)
  3. 调用Looper.loop(),线程进入阻塞态
    比如这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class LooperThread extends Thread {
public Handler mHandler;

public void run() {
Looper.prepare();

mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};

Looper.loop();
}
}

那么如果有人问你,Thread,Looper,MessageQueue,Handler数量关系是怎么样的。你可以这样告诉他。一个Thread最多只拥有一个Looper,一个Thread却是可以有多个Handler。
那么怎么理解Handler的异步或者说异步通信呢?我在主线程里面要网络数据,但是我是莫法在主线程里面直接访问网络的,所以我叫子线程去访问网络,子线程要把网络请求的结果告诉主线程,这个告诉就是回调,就是响应,通过Handler来完成。从而体现了异步。参考

Handler引起的内存泄漏

这里主要明白非静态内部类会持有外部类的引用。
所以在申明Handler的时候不要申明成static的,如果非要申明为static的就要一层如引用包裹Handler。
在onDestroy的时候移除所以的消息和回调removeCallbacksAndMessages(null)

参考

官网
Android异步消息机制Handler详解,源码剖析
Android Handler机制

This article was last updated on days ago, and the information described in the article may have changed.