首页 > 解决方案 > 发出 LiveData 以在后续挂起方法调用之间更新 UI

问题描述

当我从它们获得结果时,我正在尝试在挂起方法调用之间更新 UI。例如,这是我的 ViewModel 类。方法 a()、b() 和 c() 是挂起方法。

class MainViewModel : ViewModel() {

    lateinit var userLiveData: LiveData<String>
    var repo = MainRepo()

     fun startTest() {
          userLiveData = liveData {
             var a =  repo.a()
             System.out.println("@@@@@@@@ $a")
             emit(a)
             var b = repo.b(a)
             System.out.println("@@@@@@@@ $b")
             emit(b)
             var c = repo.c(b)
             System.out.println("@@@@@@@@ $c")
             emit(c)
         }
    }
}

这是我的活动课程,我正在观察 LiveData

viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
        viewModel.startTest()
        viewModel.userLiveData.observe(this, Observer {
            text.text = it
        })

和回购类

class MainRepo {

    suspend fun a(): String{
        delay(1000)
        return "A"
    }
    suspend fun b(a: String): String{
        delay(5000)
        return a + "B"
    }
    suspend fun c(b: String): String{
        return b + "-C"
    }
}

我的问题是,我如何在调用repo.a()orrepo.b()或之后使用结果更新 UI repo.c()。提前致谢。

标签: androidandroid-livedataandroid-viewmodelkotlin-coroutines

解决方案


您可以使用带有协程的可变实时数据来实现这一点。此外,Suspend 函数只能由协程或另一个挂起函数调用。我已经测试了下面的代码。希望这可以帮助。

您的视图模型:

val userLiveData = MutableLiveData<Map<String, String>>()

fun startTest() {
    viewModelScope.launch {
        var newVal = itemRepository.a()
        userLiveData.value = mapOf("responseTime" to newVal)
        newVal = itemRepository.b(newVal)
        userLiveData.value = mapOf("downloadSpeed" to newVal)
        newVal = itemRepository.c(newVal)
        userLiveData.value = mapOf("uploadSpeed" to newVal)
    }
}

活动:

itemViewModel.userLiveData.observe(viewLifecycleOwner, Observer { result ->
            result.get("responseTime")?.let {
                println("setting textField Response as :" +result["responseTime"])
            }
            result.get("downloadSpeed")?.let {
                println("setting textField2 Download Speed is :" +result["downloadSpeed"])
            }
            result.get("uploadSpeed")?.let {
                println("setting textField3 Upload Speed is :" +result["uploadSpeed"])
            }
        })
    itemViewModel.startTest()

回购:

class MainRepo {

    suspend fun a(): String{
        delay(1000)
        return "A"
    }
    suspend fun b(a: String): String{
        delay(5000)
        return a + "B"
    }
    suspend fun c(b: String): String{
        return b + "-C"
    }
}

输出:

setting textField Response as :A
setting textField2 Download Speed is :AB
setting textField3 Upload Speed is :AB-C

推荐阅读