【问题标题】:Avoid memory leak when Observable.create() to emit listener objectsObservable.create() 发出监听器对象时避免内存泄漏
【发布时间】:2018-01-15 10:28:48
【问题描述】:

我正在围绕 FirebaseFirestore 快照侦听器编写一个包装器,它使用 RxKotlin Observable 发出更改。

我编写了以下类,它使用 create() 方法创建可观察对象并在新数据快照可用时异步发出更改。

问题是我每次创建此类的实例并停止使用它时都会泄漏内存。在不泄漏内存的情况下重写此类的最佳方法是什么?

任何有关如何创建可以从侦听器发出对象的 Observable 的资源都会非常有帮助!

class DocumentRepository<T : ModelWithMetadata>(
        path: List<String>,
        private val model: Class<T>) {

    private var documentReference: DocumentReference

    val observable: Observable<T>

    private var emitter: ObservableEmitter<T>? = null
    private lateinit var item: T


    init {
        documentReference = FirebaseFirestore.getInstance().collection(path[0]).document(path[1])
        for (i in 2..path.lastIndex step 2)
            documentReference = documentReference.collection(path[i]).document(path[i + 1])

        observable = Observable.create(this::listenChanges)
    }

    private fun listenChanges(emitter: ObservableEmitter<T>) {
        this.emitter = emitter
        documentReference.addSnapshotListener { documentSnapshot, _ ->
            item = documentSnapshot.toObject(this.model)
            this.emitter?.onNext(item)
        }
    }

    fun get() {
        emitter?.onNext(item)
    }

    fun put(item: T) {
        item.updatedAt = TimeExtension.now()
        documentReference.set(item)
    }

    fun delete(item: T) {
        documentReference.delete()
    }
}

【问题讨论】:

标签: google-cloud-firestore rx-java2 rx-android reactivex rx-kotlin


【解决方案1】:

documentReference.addSnapshotListener 返回一个ListenerRegistration,它允许你调用ListenerRegistration#remove 来移除监听器。

而且,Emitter#setCancellable 允许您在取消订阅 Observable 时清理资源,在这种情况下分离侦听器。

所以你的listenChanges 看起来像这样:

private fun listenChanges(emitter: ObservableEmitter<T>) {
  this.emitter = emitter
  val registration = documentReference.addSnapshotListener { documentSnapshot, _ ->
    item = documentSnapshot.toObject(this.model)
    this.emitter?.onNext(item)
  }
  emitter.setCancellable { registration.remove() }
}

【讨论】:

  • 你能帮我解决一下listenChanges吗?我是科特林的新手。你为 ObservableEmitter 参数传递了什么?
  • T 是一个泛型类,在这种情况下,是您要发出的对象的类。例如,不是使用 List,而是使用 T,然后在实例化此类的对象时给出该类。这允许您将此类 (DocumentRepository) 用于您想要发出的任何类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-03
  • 2018-04-08
  • 2013-06-24
相关资源
最近更新 更多