Испускать LiveData для обновления пользовательского интерфейса между последующими вызовами метода приостановки

Я пытаюсь обновить пользовательский интерфейс между вызовами метода приостановки, когда получаю от них результаты. Например, вот мой класс 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)
         }
    }
}

и это мой класс Activity, где я наблюдаю за 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(), repo.b() или repo.c(). Заранее спасибо.


person Rookie    schedule 14.06.2019    source источник
comment
Пожалуйста, проверьте ответ.   -  person Badhrinath Canessane    schedule 15.06.2019


Ответы (1)


Вы можете добиться этого с помощью изменяемых живых данных с помощью сопрограмм. Кроме того, функция приостановки может быть вызвана только сопрограммой или другой функцией приостановки. Я протестировал приведенный ниже код. Надеюсь это поможет.

Ваша модель просмотра:

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
person Badhrinath Canessane    schedule 14.06.2019
comment
Это будет обновлять только один TextView каждый раз. Я хочу иметь 3 текстовых просмотра и обновлять их одно за другим. Возьмем пример теста скорости, первый метод обновит продолжительность пинга, второй метод обновит текстовое представление скорости загрузки, а третий метод обновит текстовое представление скорости загрузки. - person Rookie; 15.06.2019
comment
Хорошо. Я обновил ответ. Протестировал и это. Помогает наличие хэш-карты с разными ключами. Создание новых экземпляров карты помогает избежать повторного сброса того же поля. Кроме того, для простоты вы можете использовать отдельные LiveData для каждого textField. Но лично я предпочитаю приведенный выше ответ. - person Badhrinath Canessane; 15.06.2019
comment
@ Новичок Привет. Вы уже пробовали это? Как вы думаете, это правильный ответ? - person Badhrinath Canessane; 16.06.2019