UI元素在订阅之前检查其状态。

huangapple go评论71阅读模式
英文:

UI element checks its state before observes subscribes

问题

我在我的Android应用程序中更新刷新按钮状态时遇到了问题。在我的互动器中,我有一对主题来控制刷新按钮的状态。

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)
    }
}

我在我的Presenter中使用了这个互动器,它是一个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()
    }
}

我的问题是,当我打开页面时,刷新按钮是禁用的。我进行了一些调试,似乎问题的根源在于observeRefreshAction方法。这个方法创建了一个PublishSubject,当设置了refreshActionPublisher之后,立即调用了updateRefreshButtonState方法。这个方法通过调用hasObservers来检查PublishSubject是否有任何订阅者,而结果几乎总是false。这是因为PublishSubject尚未返回到Presenter,在那里我可以订阅它。

有没有办法解决这个问题?我已经尝试将updateRefreshButtonState移到doOnSubscribe中,但没有帮助。

英文:

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&lt;Boolean&gt;().apply {
            onNext(false)
        }
    }
    private var refreshActionPublisher: PublishSubject&lt;Unit&gt;? = null

    fun observeRefreshButtonState(): Observable&lt;Boolean&gt; {
        return refreshStatePublisher
    }

    fun observeRefreshAction(): Observable&lt;Unit&gt; {
        if (refreshActionPublisher?.hasComplete() == false &amp;&amp; refreshActionPublisher?.hasObservers() == true) {
            refreshActionPublisher?.onComplete()
        }

        return PublishSubject.create&lt;Unit&gt;()
            .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
            &amp;&amp; refreshActionPublisher?.hasObservers() == true)
    }
}

I use this interactor in my presenter, it's a Moxy presenter.

class PagePresenter(
        private val pageInteractor: PageInteractor
) : MvpPresenter&lt;PageView&gt; {
    override fun onFirstViewAttach() {
        super.onFirstViewAttach()

        pageInteractor
            .observeRefreshButtonState()
            .subscribe { isEnabled -&gt;
                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.

答案1

得分: 1

我试图理解这个问题,然后编写了一些代码并添加了一些注释。
所以你不需要额外的Publish Subject来调用动作,你只需要调用 `onRefreshAction()` 并改变 refreshButtonState 的当前状态。

```kotlin
import io.reactivex.Observable
import io.reactivex.subjects.BehaviorSubject
import kotlin.random.Random

class PageInteractor {

    // 初始值为 false,订阅后,订阅者将收到该值
    private val refreshButtonState = BehaviorSubject.createDefault(false)

    fun observeRefreshButtonState(): Observable<Boolean> = refreshButtonState.distinctUntilChanged()

    // 调用刷新动作
    fun onRefreshAction() {
        // 改变状态或切换状态或执行其他操作
        // 目前生成随机的下一个状态
        val nextAction = Random.nextBoolean()
        refreshButtonState.onNext(nextAction)
    }
}

<details>
<summary>英文:</summary>

I tried to understand the problem and I wrote some piece of code and added some comments.
So you don&#39;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&lt;Boolean&gt; = 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)
}

}


</details>



huangapple
  • 本文由 发表于 2020年9月2日 01:04:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/63692337.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定