场景
嗨, 我有一个带有 ViewPager 的活动。在 ViewPagerAdapter 中,我使用不同的数据创建同一片段的实例。 在每个实例中我都会初始化一个 ViewModel
val dataViewModelFactory = this.activity?.let { DataViewModelFactory(it) }
mainViewModel = ViewModelProviders.of(this, dataViewModelFactory).get(MainViewModel::class.java)
在我的片段中,当我调用 API 时,我观察到两个 MutableLiveData
mainViewModel.isResponseSuccessful.observe(this, Observer { it ->
if(it) {
//do Something
}else{
Toast.makeText(activity, "Error in Sending Request", Toast.LENGTH_SHORT).show()
}
})
mainViewModel.isLoading.observe(this, Observer {
if (it) {
println("show progress")
} else {
println("dismiss progress")
}
})
在每个片段中,单击按钮即可加载另一个片段。如果需要的话,可以调用 API 来获取数据。
问题
代码在我的片段中多次到达观察块。当我从一个片段返回到上一个片段时,即使没有调用 API,也会执行观察块上的代码。
我尝试过的
我尝试在 ViewModel 初始化中使用活动实例
mainViewModel = ViewModelProviders.of(activity,dataViewModelFactory).get(MainViewModel::class.java)
但是没有成功。
请帮忙,
它可能对你有帮助:
import java.util.concurrent.atomic.AtomicBoolean
class OneTimeEvent<T>(
private val value: T
) {
private val isConsumed = AtomicBoolean(false)
private fun getValue(): T? =
if (isConsumed.compareAndSet(false, true)) value
else null
fun consume(block: (T) -> Unit): T? =
getValue()?.also(block)
}
fun <T> T.toOneTimeEvent() =
OneTimeEvent(this)
首先,当您想在
LiveData
上发布值时,请使用 toOneTimeEvent()
扩展函数将其包装在 OneTimeEvent
中:
liveData.postValue(yourObject.toOneTimeEvent())
其次,在观察
LiveData
时,对传递的值使用consume { }
函数来获得OneTimeEvent
的特征。您将确保 consume { }
块只会执行一次。
viewModel.liveData.observe(this, Observer {
it.consume { yourObject ->
// TODO: do whatever with 'yourObject'
}
})
在这种情况下,当片段恢复时,您的代码块不会再次执行。
如果你想阻止观察者的多次调用,只需在观察者之前使用 distinctUntilChanged 。
mainViewModel.isResponseSuccessful.distinctUntilChanged().observe(this, Observer { it ->
if(it) {
//do Something
}else{
Toast.makeText(activity, "Error in Sending Request", Toast.LENGTH_SHORT).show()
}
})
mainViewModel.isLoading.distinctUntilChanged().observe(this, Observer {
if (it) {
println("show progress")
} else {
println("dismiss progress")
}
})