Handler通信机制以及存在的问题

一、Handler通信机制
1.1 Message、MessageQueue、Looper和Handler是什么?
Message,一种消息体,用于装载需要发送的对象。
MessageQueue,消息队列,用来存放所有消息。
Looper,管理者的角色,管理当前所属线程的MessageQueue,循环不断地管理MessageQueue接收和分发Message。
Handler,处理者的角色,处理和接收Looper派发出来的消息。

       Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。
       默认情况下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)。

资料链接参考:

猜你喜欢

转载自blog.csdn.net/Deaful/article/details/79815111