WeakReference не работает в Котлине

Я реализую AsyncTask в Kotlin, и мне нужен WeakReference для обратного вызова, который выполняется в onPostExecute() . Я устанавливаю ссылку слушателя перед вызовом execute() , но как только onPostExecute() , значение WeakReference равно null .

 class PhotoRotationTask(uri: Uri, filePath: String, resolver: ContentResolver) : AsyncTask<Int, Int, Int>() { private var weakRef : WeakReference<OnBitmapProcessedListener>? = null var sourceUri : Uri var resolver : ContentResolver var destPath: String init { this.sourceUri = uri this.resolver = resolver this.destPath = filePath } fun setOnBitmapProcessedListener(listener: OnBitmapProcessedListener){ weakRef = WeakReference(listener) Log.d("RotationTask", "set listener ${weakRef?.get() != null}") //This Log proves that weakRef is initialized before onPostExecute() } override fun doInBackground(vararg params: Int?): Int? { //Bitmap processing, weakRef is never called in this function } override fun onPostExecute(result: Int?) { Log.d("RotationTask", "result: $result") //This log proves that onPostExecute() is called eventually weakRef!!.get()?.onBitmapProcessed() //This implies that weakRef is not null, because app never crashes, but onBitmapProcessed is not called, so the reference is gone. } } 

Переменная- listener модифицирует пользовательский интерфейс моей активности, поэтому в нем содержится ссылка на мою активность. Активность никогда не воссоздается, мой телефон по-прежнему, никогда не поворачивается или не трогается после запуска AsyncTask. Как очищается WeakReference ?

Проблема заключается в переменной WeakReference и локальной переменной, которую вы передаете как listener .

WeakReference не удерживает объект от сбора мусора , поэтому, если нет другой надежной ссылки на него, он может быть переработан в любой момент после того, как метод, ссылающийся на него через локальную переменную, заканчивается. И это именно то, что происходит в вашем случае, так как слабая ссылка становится null .

Решение состоит в том, чтобы хранить сильную ссылку на объект, который передается как listener где-то в вызывающем коде (поскольку он использует активность, сама деятельность может хранить его в свойстве, так что время жизни listener будет соответствовать времени жизни Мероприятия).

Например, объявить свойство

 lateinit var currentListener: OnBitmapProcessedListener 

в коде действия, затем сохраните listener , созданный в этом свойстве:

 val task = PhotoRotationTask(uri, filePath, resolver) task.setOnBitmapProcessedListener(object : OnBitmapProcessedListener { // here goes the implementation }.apply { currentListener = this } // note this line ) 

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

Вам нужно провести большую ссылку на OnBitmapProcessedListener где-нибудь еще, чтобы гарантировать, что GC не очистит WeakReference.