0

In my Android app I need to create singleton with param for service class:

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

}

and use like this:

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

}

It's work fine. When I call AndroidFileUtil2.getTest() it's success print cache dir of my app. Smt like this:

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

Nice.

But on IDE I get warning like this:

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

in this line:

private lateinit var context: Context

How fix this warning in my singleton class?

Alexei
  • 14,350
  • 37
  • 121
  • 240

2 Answers2

0

You should use setContext method in your static part Check here: Access application context in companion object in kotlin

mrtcnkryln
  • 324
  • 2
  • 15
0

This error is for a generic Context because a Context could be any short-lived component like an Activity or Service. It will not give you the error for an Application, because the Application lives for the entire life of your app. And since an Application is a Context, you can use it for almost anything you'd be using a Context for, so you can change your variable type to Application to avoid the warning and prevent the risk of any leaks.

So make the lateinit var an Application, and make Application the argument type for getInstance().

The classes Activity, Service, and AndroidViewModel all have application properties you can use to pass into your getInstance() function.

But aside from avoiding the Lint warning, it would be appropriate to make AndroidFileUtil2's constructor also use Application instead of Context since it is a singleton. Lint isn't sophisticated enough to identify that and warn you about it, but as it is defined now, the AndroidFileUtil2 static reference has just as much risk of causing a leak as the static generic Context reference.

Tenfour04
  • 83,111
  • 11
  • 94
  • 154