我们在使用Handler时通常都会按照如下方式创建Handler:

1
2
3
4
5
6
val handler : Handler = object : Handler() {

override fun handleMessage(msg: Message) {
super.handleMessage(msg)
}
}

因为在java中非静态内部类会持有外部类的引用,所以内部类可以使用外部类的属性。但是Handler通常会被用来做延迟操作,这就可能导致Handler的生命周期比它外部组件的生命周期还要长,导致它引用的组件无法及时的被销毁,从而造成内存的泄露。

解决的方法:

1.保证Activity被finish()时该线程的消息队列没有这个Activity的handler内部类的引用。这个场景是及其常见的,因为handler经常被用来发延时消息。一个补救的办法就是在该类需要回收的时候,手动地把消息队列中的消息清空:handler.removeCallbacksAndMessages(null);让handler销毁, 以Activity为例如下:

1
2
3
4
5
6
7
8
9
10
11
val handler : Handler = object : Handler() {

override fun handleMessage(msg: Message) {
super.handleMessage(msg)
}
}

override fun onDestroy() {
super.onDestroy()
handler.removeCallbacksAndMessages(null)
}

2.用static修饰handler,同时传入一个外部类的弱引用(为了能够调用外部类的资源)如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
companion object {
const val CODE_LOAD_DATA: Int = 101
private class WithoutLeakHandler( activity: MainActivity) : Handler(){
private var mActivity: WeakReference<MainActivity> = WeakReference(activity)

override fun handleMessage(msg: Message) {
super.handleMessage(msg)
val activity = mActivity.get()
when(msg.what){

CODE_LOAD_DATA -> {
//data load started

}

}
}
}
}

3.自定义WeakHandler持有Hadnler引用来处理消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class WeakRefHandler : Handler {
private var mWeakReference: WeakReference<Callback>? = null

constructor(callback: Callback) {
mWeakReference = WeakReference(callback)
}

constructor(callback: Callback, looper: Looper) : super(looper) {
mWeakReference = WeakReference(callback)
}

override fun handleMessage(msg: Message) {
if (mWeakReference != null && mWeakReference!!.get() != null) {
val callback = mWeakReference!!.get()
callback?.handleMessage(msg)
}
}
}

使用如下:

1
2
3
4
5
6
7
8
val callback : Handler.Callback = object : Handler.Callback{
override fun handleMessage(p0: Message): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}

}

val handler : WeakRefHandler = WeakRefHandler(callback)

本文地址: http://www.yppcat.top/2019/08/22/自定义-Handler-时如何有效地避免内存泄漏问题/