I have a problem with updating refresh button state in my Android app. Inside my interactor I have a pair of subjects to control state of my refresh button.
class PageInteractor {
private var isRefreshActionEnabled = false
private val refreshStatePublisher by lazy {
BehaviorSubject.create<Boolean>().apply {
onNext(false)
}
}
private var refreshActionPublisher: PublishSubject<Unit>? = null
fun observeRefreshButtonState(): Observable<Boolean> {
return refreshStatePublisher
}
fun observeRefreshAction(): Observable<Unit> {
if (refreshActionPublisher?.hasComplete() == false && refreshActionPublisher?.hasObservers() == true) {
refreshActionPublisher?.onComplete()
}
return PublishSubject.create<Unit>()
.also {
refreshActionPublisher = it
updateRefreshButtonState()
}
.doOnDispose {
updateRefreshButtonState()
}
}
fun setRefreshActionEnabled(value: Boolean) {
if (isRefreshActionEnabled != value) {
isRefreshActionEnabled = value
updateRefreshButtonState()
}
}
fun onRefreshAction() {
refreshActionPublisher?.onNext(Unit)
}
private fun updateRefreshButtonState() {
refreshStatePublisher.onNext(refreshActionPublisher?.hasComplete() == false
&& refreshActionPublisher?.hasObservers() == true)
}
}
I use this interactor in my presenter, it's a Moxy presenter.
class PagePresenter(
private val pageInteractor: PageInteractor
) : MvpPresenter<PageView> {
override fun onFirstViewAttach() {
super.onFirstViewAttach()
pageInteractor
.observeRefreshButtonState()
.subscribe { isEnabled ->
viewState.setRefreshButtonEnabled(isEnabled)
}
.addTo(disposable)
}
fun onRefreshButtonClicked() {
pageInteractor.onRefreshAction()
}
}
My problem is that refresh button is disabled when I open the page. I did some debug and it seems that the source of the problem in method observeRefreshAction
. This method creates PublishSubject
, when sets refreshActionPublisher
and right after that it calls method updateRefreshButtonState
. This method checks if PublishSubject
has any subscribers by calling hasObservers
and result almost always false. It happens because PublishSubject
is not yet returned to presenter, where I can subscribe on it.
Is there any ways to fix this problem? I have tried to move updateRefreshButtonState
to doOnSubscribe
, but it didn't help.
I tried to understand the problem and I wrote some piece of code and added some comments.
So you don't need extra Publish Subject to invoke action, you can just call onRefreshAction()
and change current state of refreshButtonState.
import io.reactivex.Observable
import io.reactivex.subjects.BehaviorSubject
import kotlin.random.Random
class PageInteractor {
// Initial value is false and after subscription, subscriber will receive that value
private val refreshButtonState = BehaviorSubject.createDefault(false)
fun observeRefreshButtonState(): Observable<Boolean> = refreshButtonState.distinctUntilChanged()
// Invoke refresh action
fun onRefreshAction() {
// Change state or toggle state or something else
// Currently generate random next state
val nextAction = Random.nextBoolean()
refreshButtonState.onNext(nextAction)
}
}