英文:
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<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.
答案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'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)
}
}
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论