【问题标题】:WeakReference not working in Kotlin弱引用在 Kotlin 中不起作用
【发布时间】:2016-05-04 23:34:31
【问题描述】:

我在 Kotlin 中实现了一个 AsyncTask,我需要一个 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 变量修改了我的活动的 UI,因此它包含对我的活动的引用。 Activity 永远不会重新创建,我的手机在 AsyncTask 启动后从未旋转或触摸过。 WeakReference是怎么清除的??

【问题讨论】:

  • 您是否将局部变量作为listener 传递?它是否存储在其他地方,例如在 Activity 的属性中?
  • 是的,我传递了一个局部变量,但我没有将它存储在任何地方

标签: android kotlin


【解决方案1】:

问题出在WeakReference 和您作为listener 传递的局部变量中。

WeakReferenceknown 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
)

如果可能有多个任务和侦听器,请注意存储所有侦听器。

【讨论】:

  • 当存储的东西需要成为强引用时,拥有弱引用的目的是什么?这不会阻止对象被垃圾收集吗? (即,weakReference 的目的是,它包含的对象在需要时可以是免费的)。
  • 我不是专家,但如果我必须持有一个强引用才能正确使用同一个对象的弱引用,为什么不只是手动可以为空的对象,所以我可以决定引用何时可以被清除。
  • 通常监听接口由activity类实现,activity实例被传递给异步任务。 Activity 的引用由系统保存 - 至少在它没有被破坏的时候。通过将其在异步任务中的引用保持为 WeakReference,您就不会冒泄露活动引用的风险。根据 op 的描述,监听器是使用单独的类实现的,该类保持对 Activity 的引用——至少从原始描述中看不清楚。
【解决方案2】:

您需要在其他地方持有对 OnBitmapProcessedListener 的强引用,以确保 GC 不会清除 WeakReference。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    • 1970-01-01
    • 2021-05-22
    • 2019-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多