【问题标题】:Can this code cause memory leak in android此代码会导致android中的内存泄漏吗
【发布时间】:2020-01-16 10:13:33
【问题描述】:

我正在编写一个为多个活动缓存一些数据的类。期望是该类为每个活动执行一次初始化逻辑。但是,它也不应该导致任何内存泄漏。

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

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
        )
    }
}

【问题讨论】:

    标签: android kotlin memory-leaks


    【解决方案1】:

    使用WeakReference 很可能会防止您的代码在此处泄漏(尽管这取决于newData 是否有任何对Context 的引用——我认为它没有),维护一个保持活动的集合几乎是不可能的一个好主意,而且往往是糟糕设计的标志。

    特别是如果此类集合具有静态性质 - 就像您的情况一样。只要您的应用程序进程存在(可能是几天或更长时间),它就会存在,并且每次用户导航到另一个 Activity 或执行配置更改时,它的大小都会增长。使用WeakHashMap 可以缓解这种担忧,但无论如何它都不会使其成为更好的架构。

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

    【讨论】:

      【解决方案2】:

      我认为您可以使用 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
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-01-18
        • 2017-12-05
        • 1970-01-01
        • 2020-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-24
        • 1970-01-01
        相关资源
        最近更新 更多