在LiveData中使用viewModelScope的问题

Meh*_*iya 5 android kotlin android-livedata android-viewmodel kotlin-coroutines

我使用viewModelScopeViewModel其中要求暂停在库函数如下图所示:

视图模型

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
 }
}
Run Code Online (Sandbox Code Playgroud)

资料库

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
 }
}
Run Code Online (Sandbox Code Playgroud)

我正在观察片段中的LiveData,如下所示:

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

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

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

            }
        }
    })
Run Code Online (Sandbox Code Playgroud)

问题是我没有从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
 }
}
Run Code Online (Sandbox Code Playgroud)

我不知道我在想什么。任何帮助将不胜感激。

Luk*_*rog 5

这段代码:

viewModelScope.launch {
   deepFilterLiveData =  repo.applyFilter(compressedImage)
}
Run Code Online (Sandbox Code Playgroud)

立即返回,所以当你第一次调用onImageCompressed()方法返回nulldeepFilterLiveData。因为在你的 UI 上你使用的子句?.null返回值不会被到达。没有协程的代码可以工作,因为在这种情况下,您有顺序代码,您的 ViewModel 等待存储库调用。onImageCompressed()when

为了解决这个问题,您可以保留 ViewModel-UI 交互的 LiveData 并直接从存储库方法返回值:

class DeepFilterRepository {

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

}
Run Code Online (Sandbox Code Playgroud)

和视图模型:

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)
        }
    }     
}
Run Code Online (Sandbox Code Playgroud)