问题描述
场景
嗨, 我有一个带有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,也会执行observe块上的代码。
我尝试过的事情
我尝试在ViewModel初始化中使用活动实例
mainViewModel = ViewModelProviders.of(activity,dataViewModelFactory).get(MainViewModel::class.java)
但这没用。
请帮助
解决方法
如果您想阻止观察者的多次呼叫,您可以将MutableLiveData
更改为SingleLiveEvent
。阅读this
它可能会帮助您:
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'
}
})
在这种情况下,当片段恢复时,您的代码块将不会再次执行。