当Observable.create()发出侦听器对象时,避免内存泄漏

时间:2018-01-15 10:28:49

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

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

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

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

有关如何创建可以从侦听器发出对象的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()
    }
}

1 个答案:

答案 0 :(得分: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() }
}