2

我正在围绕 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()
    }
}
4

1 回答 1

1

documentReference.addSnapshotListener返回ListenerRegistration允许您调用ListenerRegistration#remove以删除侦听器的 a。

并且,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() }
}
于 2018-01-22T04:08:50.687 回答