Search code examples
androidkotlinrx-java2behaviorsubject

Observable subscribe not getting called on same value


I have a BehaviourSubject as a callback for my Retrofit method.

private val loadCompleted = BehaviourSubject.create<List<String>>()

Inside my retrofit OnResponse/onFailure, I call

loadCompleted.onNext(myList) //inside retrofit onResponse and 
loadCompleted.onError("Error") // inside retrofit onFailure

I am subscribed to a function which returns loadCompleted.

fun loadingCompleted() : Observable<List<String>>{return loadCompleted}

and then I subscribe to the loadingCompleted as

loadingCompleted.subscribe{list -> 
     //only called once
     anotherfun(list)
}

The first time my Retrofit function gets called, I am able to get my subscribe called but subsequent calls to the same function doesn't fire the subscribe. I am assuming the calls normally return the same value because it is just a refresh and the data might not have changed. However, I still need to get the subscribe called so I can react accordingly. I have tried both BS and ReplaySubject but the result is the same. How do I use an observable to ensure I always get the subscribe called whenever I call onNext(x)/onComplete(x) even though x might not have changed?


Solution

  • You are probably finishing your BehaviorSubject stream with onComplete/onError. If you don't want to do that, wrap x/error to some kind of Result which is sealed class and has Success and Failure subclasses. Then always use subject.onNext() to emit.

    sealed class Result<T> {
        class Success<T>(val t: T) : Result<T>()
        class Failure<T>(val e: Throwable) : Result<T>()
    }
    
    class Test {
        val subject: BehaviorSubject<Result<List<String>>> = BehaviorSubject.create()
    
        fun call() {
            subject.onNext(Result.Success(listOf("example")))
            subject.onNext(Result.Failure(RuntimeException("error")))
    
            subject.subscribe{result->
                when(result){
                    is Result.Success -> print(result.t)
                    is Result.Failure -> print(result.e.message)
                }
            }
        }
    
    }