【问题标题】:Android ViewModel MutableLiveData update multiple timesAndroid ViewModel MutableLiveData 多次更新
【发布时间】:2020-08-24 11:23:20
【问题描述】:

场景

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

但它不起作用。

请帮忙,

【问题讨论】:

  • 当你“返回”到你的片段时,ViewModelProvider 返回现有的视图模型而不是创建一个新的视图模型,因此可能已经设置了 livedata 并发出它所持有的任何值。
  • @Pawel 是的,假设在片段 A 中,我将该值设为“真”并执行我所做的所有处理。然后我转到片段 B。现在当我回到片段 A 时,它再次发出“真实”值?我该如何防止这种情况发生,我不想在第一次使其“真实”时进行所有处理。
  • 要么添加一个方法,当你“离开”你的片段时清除你的实时数据,要么根本不使用视图模型。
  • 谢谢,我如何清除我的 livedata @Pawel

标签: android android-fragments android-livedata android-viewmodel mutablelivedata


【解决方案1】:

如果您想防止多次调用您的观察者,您只需将MutableLiveData 更改为SingleLiveEvent。阅读this

【讨论】:

  • 在这种情况下,如果我在我的片段A中,调用一个API并显示progressdialog,它只会显示一次,而不是其他API调用。我希望仅当我的片段在屏幕上时才观察我的实时数据,并且不保留我回来时的值
【解决方案2】:

也许对你有帮助:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 2014-01-06
    • 1970-01-01
    相关资源
    最近更新 更多