内存泄露分析,从此简单。

453 阅读2分钟

内存泄露分析,从此简单

--- 喜欢项目,喜欢分析内存泄露。

刚进入到项目不久(还未转正),测试还没给反馈之前,简单看一下项目的内存泄露情况吧。

1.首先引入LeakCanary

   debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'

2.重新构建APP,运行。

打开,每个ActivityFragment,对话框,弹窗等等。过5分钟,从App附属的Leaks App内查看报告。

目前的泄露报告 3.分析

我主要分析,这个ToastShow.mToastStrategy

先看代码,从代码去分析内存泄露情况。

class CustomSysToastStrategy : IToastStrategy {
    private var mToast: ToastCompat? = null
fun show(context:Context){
cancel()
        //系统toast采用依赖application防止内存泄漏
        val appContext = context.applicationContext
        val toastView = LayoutInflater.from(appContext).inflate(R.layout.toast_custom, null)
        val tv = toastView.findViewById<TextView>(R.id.mCustomToastMessage)
        tv.text = str
        val baseToast = Toast(appContext)
        baseToast.setGravity(Gravity.CENTER, 0, 0)
        baseToast.duration = duration
        baseToast.view = toastView
        mToast = ToastCompat.makeText(appContext, baseToast)
        mToast!!.show()
}
​
  override fun cancel() {
        if (mToast != null) {
            mToast!!.cancel()
            mToast = null
        }
    }
}

从代码得知,两个方法一个负责(show方法)展示Toast,一个负责回收(cancel方法)Toast

先看show 方法。

第一行直接是cancel,为了防止多个Toast同时触发,可能会导致无限个Toast

第二行:是为了全局能使用Toast(其实不需要).

第三行:从布局文件解析出一个View(toastView)

后面创建Toast对象(baseToast), ToastCompat (mToast),一个个的塞进去,俄罗斯套娃模式。

//其实一个对象就够了。

在cancel里面,取消Toast,把toast的引用指空。

问题在cancel这个方法里。

mToast=null

猜测:这步骤操作,只能去清空mToast, 但是还是不能解决toastView,baseToast的内存资源回收。

这一点从Leaks的报告里也能推导出。或者cancel方法内打印是否null的判断。

4.报告

Leaks的报告内容如下:

cap1.png

关键内容:android.widget.LinearLayout instance Leaking:YES

描述的是,LinearLayout 实例触发了View.onDetachedFromWindow()方法,但是无法被回收。

  1. 优化

    思路是把分配的对象拉到方法外,在cancel里面进行null赋值回收资源。

    private var toastView: View? = null
    private var baseToast: Toast?=null
    private var mToast: ToastCompat? = null//...省略了部分代码。
    override fun cancel() {
        if (mToast != null) {
            toastView=null
            baseToast=null
            mToast!!.cancel()
            mToast = null
        }
    }

The end.