一、Handler通信机制
1.1 Message、MessageQueue、Looper和Handler是什么?
Message,一种消息体,用于装载需要发送的对象。
MessageQueue,消息队列,用来存放所有消息。
Looper,管理者的角色,管理当前所属线程的MessageQueue,循环不断地管理MessageQueue接收和分发Message。
Handler,处理者的角色,处理和接收Looper派发出来的消息。
Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。
默认情况下Handler会与其被定义时所在线程的Looper绑定,比如,Handler在主线程中定义,那么它是与主线程的Looper绑定。
默认情况下Handler会与其被定义时所在线程的Looper绑定,比如,Handler在主线程中定义,那么它是与主线程的Looper绑定。
1.2 通信流程
创建Handler,并采用当前线程的Looper开启消息循环;
Handler通过sendMessage(Message)或post(Runnable)发送消息,调用enqueueMessage让消息进入消息队列中;
Looper循环检测消息队列中的消息,若有消息则取出该消息,并调用该消息持有的handler的dispatchMessage方法,回调到创建Handler线程中重写的handleMessage里执行。
1.3 Handler中分发消息的一些方法
post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
post类方法,允许你安排一个Runnable对象到主线程队列中。
send类方法, 允许你安排一个带数据的Message对象到队列中。
1.4 Looper.prepare()和Looper.loop()方法
Looper.prepare()表示为当前线程创建一个消息队列。
Looper.loop()表示让Looper开始工作,不断地从消息队列中取数据。
默认情况下android中新诞生的线程是没有开启消息循环的。(主线程除外,主线程系统会自动为其创建Looper对象,开启消息循环。)
在非主线程中直接new Handler() 会报错。原因是非主线程中默认没有创建Looper对象,需要先调用Looper.prepare()启用Looper。
二、Handler 存在的问题
2.1 内存方面问题:
内存泄漏
Handler如果为非静态内部类,则会引用外部类对象。当 Activity finish 时,Handler可能并未执行完,从而引起 Activity 的内存泄漏。
2.2 异常方面问题:
空指针
当 Activity finish 时,在 onDestroy 方法中释放了一些资源。此时 Handler 执行到 handleMessage方法,但相关资源已经被释放,从而引起空指针的异常。
2.3 解决方案
内存方面:使用
静态内部类创建 handler 对象,且对 Activity 持有
弱引用。
异常方面:在 onDestory 中把消息队列 MessageQueue 中的消息给 remove 掉。
Runnable用handler.
removeCallbacks(postRunnable),
Message用 handler.
removeMessage(what)。
资料链接参考: