内存监测工具
Android Studio 自带工具 Profiler
排查泄露的出处主要有两处:
CoroutineScope(Dispatchers.Main)
协程未释放匿名内部类
对外部类有强引用
协程未释放
kotlin
// CoroutineScope 未在 destroy 方法中 cancel
fun recycleViewScrollZoo() {
LogUtils.i(TAG, "recycleViewScrollZoo")
CoroutineScope(Dispatchers.Main).launch{
FlowBus.events.collect{ event ->
when(event){
is EventWidget -> {
LogUtils.i(TAG, "recycleViewScrollZoo event.widgetName = : ${event.widgetName}")
scrollByWidgetName(event.widgetName)
}
}
}
}
}
造成内存泄漏的情况
选择一个类,可以查看具体的泄漏对象
解决方案
找到泄漏对象,在 destroy 方法中 cancel 任务
匿名内部类
kotlin
private val mainHandler = Handler(Looper.getMainLooper())
// 匿名内部类
private val launcherStyleObserver = object : ContentObserver(mainHandler) {
override fun onChange(selfChange: Boolean, uri: Uri?) {
super.onChange(selfChange, uri)
if (uri != null && uri.toString() == Settings.Global.getUriFor(KEY_LAUNCHER_STYLE)
.toString()
) {
startHomeWhenInBackGround()
updateLauncherStyle()
}
}
}
匿名内部类持有外部类的引用,修改代码如下:
kotlin
private val launcherStyleObserver = LauncherStyleObserver(mainHandler, this)
// 使用静态内部类和弱引用:将匿名内部类改为静态内部类,并使用弱引用持有外部类的引用
private class LauncherStyleObserver(handler: Handler, activity: MainActivity) : ContentObserver(handler) {
// 弱引用
private val activityReference = WeakReference(activity)
override fun onChange(selfChange: Boolean, uri: Uri?) {
super.onChange(selfChange, uri)
val activity = activityReference.get()
if (uri != null && uri.toString() == Settings.Global.getUriFor(KEY_LAUNCHER_STYLE)
.toString()
) {
activity?.startHomeWhenInBackGround()
activity?.updateLauncherStyle()
}
}
}
解决方案:使用静态内部类和弱引用,将匿名内部类改为静态内部类,并使用弱引用持有外部类的引用