Проблема в использовании viewModelScope с LiveData - PullRequest
1 голос
/ 01 мая 2019

Я использую viewModelScope в ViewModel, который вызывает функцию приостановки в репозитории, как показано ниже:

ViewModel

class DeepFilterViewModel(val repo: DeepFilterRepository) : ViewModel() {

var deepFilterLiveData: LiveData<Result>? = null

 fun onImageCompressed(compressedImage: File): LiveData<Result>? {
    if (deepFilterLiveData == null) {
        viewModelScope.launch {
            deepFilterLiveData =  repo.applyFilter(compressedImage)
        }

    }
    return deepFilterLiveData
 }
}

Репозиторий

class DeepFilterRepository {

suspend fun applyFilter(compressedImage: File): LiveData<Result> {
    val mutableLiveData = MutableLiveData<Result>()
    mutableLiveData.value = Result.Loading

    withContext(Dispatchers.IO) {
        mutableLiveData.value = Result.Success("Done")

    }
    return mutableLiveData
 }
}

Я наблюдаю LiveData из фрагмента, как показано ниже:

 viewModel.onImageCompressed(compressedImage)?.observe(this, Observer { result ->
        when (result) {

            is Result.Loading -> {
                loader.makeVisible()
            }

            is Result.Success<*> -> {
                // Process result

            }
        }
    })

Проблема в том, что я не получаю значения из LiveData.Если я не использую viewModelScope.launch {}, как показано ниже, то все работает нормально.

class DeepFilterViewModel(val repo: DeepFilterRepository) : ViewModel() {

var deepFilterLiveData: LiveData<Result>? = null

 fun onImageCompressed(compressedImage: File): LiveData<Result>? {
    if (deepFilterLiveData == null) {
            deepFilterLiveData =  repo.applyFilter(compressedImage)
    }
    return deepFilterLiveData
 }
}

Я не знаю, что мне не хватает.Любая помощь будет оценена.

1 Ответ

1 голос
/ 01 мая 2019

Этот код:

viewModelScope.launch {
   deepFilterLiveData =  repo.applyFilter(compressedImage)
}

немедленно возвращается, поэтому при первом вызове метода onImageCompressed () вы возвращаете null как deepFilterLiveData. Потому что в вашем пользовательском интерфейсе вы используете? для нулевого возвращаемого значения onImageCompressed () предложение when не будет достигнуто. Код без сопрограммы работает, потому что в этом случае у вас есть последовательный код, ваша ViewModel ожидает вызова репозитория.

Чтобы решить эту проблему, вы можете сохранить LiveData для взаимодействия ViewModel-UI и вернуть значения непосредственно из метода репозитория:

class DeepFilterRepository {

    suspend fun applyFilter(compressedImage: File) = withContext(Dispatchers.IO) {
        Result.Success("Done")
    }

}

И ViewModel:

class DeepFilterViewModel(val repo: DeepFilterRepository) : ViewModel() {

    private val _backingLiveData = MutableLiveData<Result>()
    val deepFilterLiveData: LiveData<Result>
       get() = _backingLiveData

    fun onImageCompressed(compressedImage: File) {
        // you could also set Loading as the initial state for _backingLiveData.value           
       _backingLiveData.value = Result.Loading
        viewModelScope.launch {
            _backingLiveData.value = repo.applyFilter(compressedImage)
        }
    }     
}
...