Android ViewModel MutableLiveData 多次更新

问题描述 投票:0回答:3

场景

嗨, 我有一个带有 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)

但是没有成功。

请帮忙,

android android-fragments android-livedata android-viewmodel mutablelivedata
3个回答
1
投票

如果您想防止观察者多次调用,您只需将

MutableLiveData
更改为
SingleLiveEvent
即可。阅读


1
投票

它可能对你有帮助:

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'
            }
        })

在这种情况下,当片段恢复时,您的代码块不会再次执行。


0
投票

如果你想阻止观察者的多次调用,只需在观察者之前使用 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")
        }
})
© www.soinside.com 2019 - 2024. All rights reserved.