Android ViewModel MutableLiveData 多次更新
Android ViewModel MutableLiveData update multiple times
场景
你好,
我有一个带有 ViewPager 的 Activity。在 ViewPagerAdapter 中,我创建了具有不同数据的同一片段的实例。
在每个实例中,我都会初始化一个 ViewModel
val dataViewModelFactory = this.activity?.let { DataViewModelFactory(it) }
mainViewModel = ViewModelProviders.of(this, dataViewModelFactory).get(MainViewModel::class.java)
在我的片段中,我在调用 APIs
时观察到两个 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 初始化中使用 activity 实例
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)
首先,当您想 post LiveData
上的值时,使用 toOneTimeEvent()
扩展函数将其包装在 OneTimeEvent
:
中
liveData.postValue(yourObject.toOneTimeEvent())
其次,当你在LiveData
上观察时,对传递的值使用consume { }
函数来获得OneTimeEvent
的特征。您将确定 consume { }
的块将只执行一次。
viewModel.liveData.observe(this, Observer {
it.consume { yourObject ->
// TODO: do whatever with 'yourObject'
}
})
在这种情况下,当片段恢复时,您的代码块不会再次执行。
场景
你好, 我有一个带有 ViewPager 的 Activity。在 ViewPagerAdapter 中,我创建了具有不同数据的同一片段的实例。 在每个实例中,我都会初始化一个 ViewModel
val dataViewModelFactory = this.activity?.let { DataViewModelFactory(it) }
mainViewModel = ViewModelProviders.of(this, dataViewModelFactory).get(MainViewModel::class.java)
在我的片段中,我在调用 APIs
时观察到两个 MutableLiveDatamainViewModel.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 初始化中使用 activity 实例
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)
首先,当您想 post LiveData
上的值时,使用 toOneTimeEvent()
扩展函数将其包装在 OneTimeEvent
:
liveData.postValue(yourObject.toOneTimeEvent())
其次,当你在LiveData
上观察时,对传递的值使用consume { }
函数来获得OneTimeEvent
的特征。您将确定 consume { }
的块将只执行一次。
viewModel.liveData.observe(this, Observer {
it.consume { yourObject ->
// TODO: do whatever with 'yourObject'
}
})
在这种情况下,当片段恢复时,您的代码块不会再次执行。