开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情
3.消息机制的分析
1.了解Message
可理解为线程间通讯的数据单元,可通过message携带需要的数据 创建Message的方法
- val message:Message= Message()
- val message1:Message=Message.obtain()//它利用了Message中消息池(sPool)
封装数据:
int what:标识
int arg1:保存int数据
int arg2:保存int数据
Object obj:保存任意时刻的数据
Long when :记录应该被处理的时间值,若为即时消息,时间值=发送时间,若为延时消息,时间值=发送时间+延迟时间
Handler target:用来处理消息的Handler对象,就是发送消息的Handler
Runnable callback:用来处理消息的回调器
Message next:指向下一个Message用来形成一个链表
Message sPool:用来缓存处理过的Message,以便复用
2.了解Handler
Handler是Message的处理器,同时也负责消息的发送和移除的工作
(1)Handler的构造方法
Android API 30以上,使用Handler()方法时会显示删除线,并提示相关的方法已经被弃用,不建议使用。如图所示:
但是安卓不是弃用Handler这个类,而只是弃用Handler的两个构造方法:
1. Handler()
1. Handler(callback:Handler.Callback)
安卓建议采用如下方法来解决
1.使用Executor
2.明确指定Looper
3.使用Looper.getMainLooper()定位并使用主线程的Looper
4.如果又想在其他线程,又想要不出bug,请使用Handler(looper:Looper)或者Handler(Looper.myLooper())这两个构造方法。
(2)Handler导致的内存泄漏问题
在Android中最常用的一种内存泄漏是Handler导致的泄漏,原因:
(1)在Activity被摧毁时,延迟消息还没发出,Handler可能有未执行完或者正在执行的Message,MessagesQueue就会持有这个消息的引用,导致Handler持有Activity的引用,进而导致GC无法回收Activity。
(2)Handler中有还没执行完的Message,还在运行,而运行中的子线程不会被回收,所以就导致了内存泄漏。
解决方法:
1.在Activity的onDestroy()方法中,清空Handler中的未执行或者正在执行的Message和Callbacks
1. override fun onDestroy() {
1. super.onDestroy()
1. handler.removeCallbacksAndMessages(null)
1. }
2.static+弱引用
class MyHandler(activity: HandlerActivity):Handler(Looper.getMainLooper()){
private val myWeakReference:WeakReference<HandlerActivity> = WeakReference(activity)
override fun handleMessage(msg: Message) {//处理消息的回调方法
myWeakReference.get()?.run {
...
}
}
}
(3)Handler的常用方法:
发送即时消息:sendMessage(msg Message)
发送延时消息:sendMessageDelayed(msg Message,delayMillis Long)
处理方法:handleMessage(msg Message)(回调方法)
移除还未处理的消息:removeMessages(what int)