Как избежать контекста Android в поле stati c в синглтоне? - PullRequest
0 голосов
/ 30 января 2020

В моем приложении 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

Как исправить это предупреждение в моем синглтон-классе?

Ответы [ 2 ]

0 голосов
/ 30 января 2020

Эта ошибка относится к обобщенному c Context, поскольку Context может быть любым кратковременным компонентом, таким как действие или служба. Это не даст вам ошибку для Application, потому что приложение живет в течение всей жизни вашего приложения. И поскольку Application является Context, вы можете использовать его практически для всего, для чего вы будете использовать Context, поэтому вы можете изменить тип переменной на Application, чтобы избежать предупреждения и предотвратить риск любые утечки.

Так что сделайте lateinit var в Application и сделайте Application тип аргумента для getInstance().

Классы Activity, Service и AndroidViewModel у всех есть application свойства, которые вы можете использовать для передачи в вашу getInstance() функцию.

Но кроме того, чтобы избежать предупреждения Lint, было бы целесообразно, чтобы конструктор AndroidFileUtil2 также использовал Application вместо Context, так как это синглтон. Lint не достаточно сложен, чтобы идентифицировать это и предупредить вас об этом, но, как он определен сейчас, ссылка AndroidFileUtil2 stati c имеет такой же риск вызвать утечку, как и ссылка stati c generi c Context ссылка.

0 голосов
/ 30 января 2020

Вы должны использовать setContext метод в вашей части c. Проверьте здесь: Доступ к контексту приложения в сопутствующем объекте в kotlin

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...