livedata-ktx icon indicating copy to clipboard operation
livedata-ktx copied to clipboard

PublishLiveDataKtx not remove observer by lifecycle event

Open jukov opened this issue 6 years ago • 0 comments

Code from https://github.com/Shopify/livedata-ktx/blob/master/livedata-ktx/src/main/java/com/shopify/livedataktx/PublishLiveDataKtx.kt:

   override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
        val observeSinceVersion = version
        val wrapper = observerWrappers.getOrElse(observer, Observer {
            if (!isPublish || version > observeSinceVersion) {
                observer.onChanged(it)
            }
        })
        observerWrappers.putIfAbsent(observer, wrapper)
        super.observe(owner, wrapper)
    }

    override fun observeForever(observer: Observer<in T>) {
        val observeSinceVersion = version
        val wrapper = observerWrappers.getOrElse(observer, Observer {
            if (!isPublish || version > observeSinceVersion) {
                observer.onChanged(it)
            }
        })
        observerWrappers.putIfAbsent(observer, wrapper)
        super.observeForever(wrapper)
    }

    override fun removeObserver(observer: Observer<in T>) {
        observerWrappers.get(observer)?.let { super.removeObserver(it) }
        observerWrappers.removeIfPresent(observer)
    }

When we call observeForever(), all looks good and calling removeObserver() with same Observer working as expected.

But if we call observe() and later lifecycle move to Destroyed state, system call removeObserver() with wrapped Observer, and we try to find it in observedWrappers among non-wrapped observers. Pair instances with weak references to observers just accumulated in array until livedata instance not GCed.

I don't know clear solution of this problem, suppose we can check wrapped and non-wrapped observers both when removing.

jukov avatar Dec 17 '19 21:12 jukov