【问题标题】:How avoid Android context in static field in Singleton?如何在 Singleton 的静态字段中避免 Android 上下文?
【发布时间】:2020-01-30 12:03:00
【问题描述】:

在我的 Android 应用中,我需要为服务类创建带有参数的单例:

class AndroidFileUtil2 private constructor(newContext: Context) {

    init {
        context = newContext
        if (BuildConfig.DEBUG)
            Log.d(TAG, "CONSTRUCTOR: context = $context")
    }

    companion object {
        private var instance: AndroidFileUtil2? = null
        private lateinit var context: Context

        private val TAG = AndroidFileUtil2::class.java.name

        @Synchronized
        fun getInstance(context: Context): AndroidFileUtil2 {
            if (instance == null) {
                instance = AndroidFileUtil2(context)
            }
            return instance as AndroidFileUtil2
        }

        fun getTest() {
            if (BuildConfig.DEBUG)
                Log.d(TAG, "getTest(): context_cacheDir = ${context.cacheDir}")
        }
    }

}

并像这样使用:

class Main : Application() {
  override fun onCreate() {
      super.onCreate()
      AndroidFileUtil2.getInstance(appContext)
      AndroidFileUtil2.getTest()
    }

}

一切正常。当我调用AndroidFileUtil2.getTest() 时,它成功打印了我的应用程序的缓存目录。像这样:

getTest(): context_cacheDir = /data/user/0/com.myproject.client.debug/cache

不错。

但在 IDE 上我收到这样的警告:

Do not place Android context classes in static fields. This is a memory leak

在这一行:

private lateinit var context: Context

如何在我的单例类中修复此警​​告?

【问题讨论】:

    标签: android kotlin


    【解决方案1】:

    您应该在静态部分使用setContext 方法 在这里检查: Access application context in companion object in kotlin

    【讨论】:

      【解决方案2】:

      此错误适用于通用 Context,因为 Context 可能是任何短期组件,例如 Activity 或 Service。它不会为您提供Application 的错误,因为应用程序在您的应用程序的整个生命周期中都存在。由于ApplicationContext,您几乎可以将它用于您将使用Context 的任何东西,因此您可以将变量类型更改为Application 以避免警告并防止风险任何泄漏。

      所以将lateinit var 设为Application,并将Application 设为getInstance() 的参数类型。

      ActivityServiceAndroidViewModel 类都有 application 属性,您可以使用这些属性将其传递到您的 getInstance() 函数中。

      但是除了避免 Lint 警告之外,让 AndroidFileUtil2 的构造函数也使用 Application 而不是 Context 是合适的,因为它是一个单例。 Lint 不够复杂,无法识别并警告您,但正如它现在定义的那样,AndroidFileUtil2 静态引用与静态通用 Context 引用一样具有导致泄漏的风险。

      【讨论】:

        猜你喜欢
        • 2018-01-11
        • 2018-08-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多