Как обойти предупреждение об утечке памяти (создание класса-сиглета, расширяющего AsyncTask) - PullRequest
0 голосов
/ 06 марта 2019

Я создал коммуникационное приложение UDP, и оно работает очень хорошо (пока).Для получения пакетов UDP я использую класс расширения AsyncTask.

Для ясности (и краткости) я разделил код на отдельные файлы kotlin.

MainActivity.kt обрабатывает такие элементы пользовательского интерфейса, как нажатие кнопки и создание объектов
LongTask.kt определяет класс LongTask, расширяющий AsyncTask (Код получателя UDP)

Я создаю экземпляр LongTask для события нажатия кнопки , используя следующее

task = object : LongTask("$idx"){
                override fun onProgressUpdate(vararg values: String?) {
                    super.onProgressUpdate(*values)
                    Log.d(TAG, "On UI thread")
                }
            }

task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "")

Однако вышеприведенные строки кода выделеныв желтом и предупреждают о возможной утечке памяти.

Как написать код защиты от утечек, чтобы обойти это предупреждение?

1 Ответ

0 голосов
/ 07 марта 2019
task = object : LongTask("$idx"){
    override fun onProgressUpdate(vararg values: String?) {
        super.onProgressUpdate(*values)
        Log.d(TAG, "On UI thread")
    }
}

Эта строка создаст анонимный внутренний класс, который выходит из LongTask класса.Внутренний класс имеет неявную ссылку на свой внешний класс, в данном случае MainActivity class.

Если действие завершено до завершения асинхронной задачи, то GC будет пропускать или не собирать действие, потому что оно все еще передается в асинхронной задаче.

Решение: КИзбегайте использования API WeakReference.Кроме того, LongTask - это отдельный класс, поэтому нам нужно определить интерфейс для передачи данных обратно в действие.

Сначала объявите интерфейс

OnProgressUpdateListener.kt

interface OnProgressUpdateListener {
    fun onProgressUpdate(vararg values: String?)
}

Во-вторых, измените класс asynctask.Просто сосредоточьтесь на OnProgressUpdateListener части, потому что я не знаю, как именно выглядит ваш класс.

LongTask.kt

class LongTask(val idx: String, listener: OnProgressUpdateListener) : AsyncTask<String, String, Unit>() {

    private val mListener: WeakReference<OnProgressUpdateListener>? = WeakReference(listener)

    override fun doInBackground(vararg params: String?) {

    }

    override fun onProgressUpdate(vararg values: String?) {
        mListener?.get()?.onProgressUpdate(*values)
    }
}

Наконец, позвольте заданию реализоватьOnProgressUpdateListener.

MainActivity.kt

class MainActivity : AppCompatActivity(), OnProgressUpdateListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        task = LongTask("$idx", this)
        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "")
    }

    override fun onProgressUpdate(vararg values: String?) {
        // Update your progress on UI thread here
        Log.d(TAG, "On UI thread")
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...