2016-05-04 2 views
6

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

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?

+0

Вы передаете локальную переменную как «слушатель»? Хранит ли он где-то в другом месте, например. в собственности Деятельности? – hotkey

+0

yes Я передаю локальную переменную, но я ее нигде не храню – gesuwall

ответ

5

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

WeakReference является known not to keep an object from being garbage collected, поэтому, если нет другого достижимы сильная ссылка к нему, он может быть возвращен в любой момент, как только метод, ссылающегося его через местные отделки переменной. И это именно то, что происходит в вашем случае, так как слабая ссылка становится 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 
) 

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

+0

Какая цель иметь слабое значение, когда что-то, что оно хранит, должно быть StrongReference? Разве это не помешало бы объекту собрать мусор? (т. е. цель weakReference заключается в том, что объект, который он содержит, может быть свободен, когда это необходимо). – Elye

0

Необходимо, чтобы ссылка на OnBitmapProcessedListener содержалась в другом месте, чтобы гарантировать, что GC не очистит WeakReference.

Смежные вопросы