WeakReference不在Kotlin工作
我在Kotlin中实现了一个AsyncTask
,并且我需要一个在onPostExecute()
方法中运行的回调WeakReference
。 我在调用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
如何清除?
问题在于你作为listener
传递的WeakReference
和局部变量。
已知 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。