实时数据观察器在创建的片段上触发了两次
Live data observer triggered twice on fragment created
我遇到的问题实际上不是错误或大问题。一切正常,但仍然让我烦恼。
在片段 pbserver 中:
viewModel.pageNumbersPosition.observe(viewLifecycleOwner) {
if (it!=null) {
SharedPreferenceHelper.pagesNumber = viewModel.pageNumbersArray.value?.get(it)
DLog.d("Set: ${viewModel.pageNumbersArray.value?.get(it)}}")
//Log shows twice as start
}
}
视图模型:
class MenuViewModel : ViewModel() {
var pageNumbersArray = MutableLiveData(getPageNumbering())
var pageNumbersPosition = MutableLiveData(pageNumbersArray.value?.indexOf(SharedPreferenceHelper.pagesNumber))
private fun getPageNumbering():Array<String> {
val list = mutableListOf<String>()
for (i in 1..25) {
list.add(i.toString())
}
return list.toTypedArray()
}
}
微调器:
<Spinner
android:id="@+id/spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@{viewModel.pageNumbersArray}"
android:selectedItemPosition="@={viewModel.pageNumbersPosition}"/>
发生的事情是 viewModel.pageNumbersPosition.observe
在开始时触发了两次。一次是从片段开始,第二次是在微调器设置时。这实际上应该发生,但我不喜欢共享首选项设置两次。
我遇到了一个方便的 class SingleLiveEvent
,我们可以使用它代替 ViewModel
class 中的 LiveData
,以便在订阅后仅发送新的更新。
class SingleLiveEvent<T> : MutableLiveData<T>() {
private val pending = AtomicBoolean(false)
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
super.observe(owner, Observer<T> { t ->
if (pending.compareAndSet(true, false)) {
observer.onChanged(t)
}
})
}
override fun setValue(t: T?) {
pending.set(true)
super.setValue(t)
}
fun call() {
postValue(null)
}
}
此 LiveData
扩展仅在显式调用 setValue()
或 call()
时调用可观察对象。
更新,带参数的主构造函数:
class SingleLiveEvent<T>(value: T) : MutableLiveData<T>(value) {...}
您可以检查您的共享中是否存在相同的值以避免双重设置
if (it!=null) {
viewModel.pageNumbersArray.value?.get(it).let{ value ->
if (SharedPreferenceHelper.pagesNumber != value)
SharedPreferenceHelper.pagesNumber = value
}
}
我遇到的问题实际上不是错误或大问题。一切正常,但仍然让我烦恼。
在片段 pbserver 中:
viewModel.pageNumbersPosition.observe(viewLifecycleOwner) {
if (it!=null) {
SharedPreferenceHelper.pagesNumber = viewModel.pageNumbersArray.value?.get(it)
DLog.d("Set: ${viewModel.pageNumbersArray.value?.get(it)}}")
//Log shows twice as start
}
}
视图模型:
class MenuViewModel : ViewModel() {
var pageNumbersArray = MutableLiveData(getPageNumbering())
var pageNumbersPosition = MutableLiveData(pageNumbersArray.value?.indexOf(SharedPreferenceHelper.pagesNumber))
private fun getPageNumbering():Array<String> {
val list = mutableListOf<String>()
for (i in 1..25) {
list.add(i.toString())
}
return list.toTypedArray()
}
}
微调器:
<Spinner
android:id="@+id/spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@{viewModel.pageNumbersArray}"
android:selectedItemPosition="@={viewModel.pageNumbersPosition}"/>
发生的事情是 viewModel.pageNumbersPosition.observe
在开始时触发了两次。一次是从片段开始,第二次是在微调器设置时。这实际上应该发生,但我不喜欢共享首选项设置两次。
我遇到了一个方便的 class SingleLiveEvent
,我们可以使用它代替 ViewModel
class 中的 LiveData
,以便在订阅后仅发送新的更新。
class SingleLiveEvent<T> : MutableLiveData<T>() {
private val pending = AtomicBoolean(false)
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
super.observe(owner, Observer<T> { t ->
if (pending.compareAndSet(true, false)) {
observer.onChanged(t)
}
})
}
override fun setValue(t: T?) {
pending.set(true)
super.setValue(t)
}
fun call() {
postValue(null)
}
}
此 LiveData
扩展仅在显式调用 setValue()
或 call()
时调用可观察对象。
更新,带参数的主构造函数:
class SingleLiveEvent<T>(value: T) : MutableLiveData<T>(value) {...}
您可以检查您的共享中是否存在相同的值以避免双重设置
if (it!=null) {
viewModel.pageNumbersArray.value?.get(it).let{ value ->
if (SharedPreferenceHelper.pagesNumber != value)
SharedPreferenceHelper.pagesNumber = value
}
}