WeakReference does not work in Kotlin

I am implementing AsyncTask in Kotlin and I need a WeakReference for the callback that is executed in the onPostExecute() method. I set the listener link before calling execute() , but after calling onPostExecute() value of WeakReference is 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. } } 

The listener variable changes the interface of my activity, so it contains a link to my activity. Activity is never recreated, my phone is still, never rotates or starts moving after starting AsyncTask. How is WeakReference cleared?

+6
source share
2 answers

The problem is the WeakReference and the local variable that you pass as a listener .

WeakReference known that this object does not contain garbage collection , therefore, if there is no other available reference to it, it can be processed at any time as soon as the method refers to it through a local variable. And this is exactly what happens in your case, as a weak link becomes null .

The solution is to keep a strong reference to an object that is passed as a listener somewhere in the calling code (since it uses an action, the activity itself can store it in the property, so that the listener lifetime will correspond to the activity).

For example, declare a property

 lateinit var currentListener: OnBitmapProcessedListener 

in the action code, then save the listener created in this property:

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

If several tasks and listeners are possible, take care to keep all listeners.

+5
source

You need to have a strong reference to the OnBitmapProcessedListener somewhere else to ensure that the GC does not clear the WeakReference.

0
source

All Articles