这段代码会导致Android中的内存泄漏吗

时间:2019-09-15 07:57:14

标签: android kotlin memory-leaks

我正在编写一个类,该类为多个活动缓存一些数据。期望该类对每个活动都通过一次初始化逻辑。但是,它也不应引起任何内存泄漏。

如果有人可以查看此代码以检查潜在的内存泄漏,将很有帮助。也欢迎其他评论。

class AbcManager private constructor(private val data : Abc) {

    fun fromAbc(a : A) : B? = data.someMethod(a)

    companion object {

        private val abcManagerCache : MutableList<AbcManagerCacheItem> = mutableListOf()

        fun of(context : Activity) : AbcManager {

            val abcManagerFromCache = attemptFromCache(context)
            if(abcManagerFromCache != null) return abcManagerFromCache
            val newData = //some operation that uses the context
            val abcManager = AbcManager(newData)
            abcManagerCache.add(AbcManagerCacheItem(
                    context = WeakReference(context),
                    abcManager = abcManager
            ))
            return abcManager
        }

        private fun attemptFromCache(context : Context) : AbcManager? {
            abcManagerCache.forEach {
                val contextFromCache = it.context.get()
                if( null!= contextFromCache && context == contextFromCache) {
                    return it.abcManager
                }
            }
            return null
        }

        private class AbcManagerCacheItem(
                val context : WeakReference<Context>,
                val abcManager : AbcManager
        )
    }
}

2 个答案:

答案 0 :(得分:0)

我认为您可以使用WeakHashMap并摆脱包装管理器类,从而变得更简单-

object AbcCache {
    private val cache = WeakHashMap<Context, Abc>()

    fun putInCache(context: Activity): Abc {
        val dataFromCache = cache[context]
        if (dataFromCache != null) return dataFromCache

        val newData: T = //some operation that uses the context
        cache[context] = newData
        return newData
    }
}

答案 1 :(得分:0)

使用WeakReference最有可能防止您的代码在这里泄漏(尽管这取决于newData是否对Context进行了引用-我认为没有),维护了一个集合保持“活动”几乎从来不是一个好主意,并且(通常是)一个不良设计的标志。

尤其是这种集合是否具有静态性质时(如您的情况)。只要您的应用进程有效(可能需要几天或更长的时间),它就会一直存在,并且每次用户导航到另一个Activity或执行配置更改时,它的大小都会增加。可以通过使用WeakHashMap来减轻这种担忧,但是它并不能使它成为更好的体系结构。

如果每个AbcManager实例仅初始化一次Activity,为什么不将其保留为一个字段呢?如果您想确保在by lazy处于适当状态之前不要实例化它,可以使用Activity