程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了Android 协程和 LiveData大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决Android 协程和 LiveData?

开发过程中遇到Android 协程和 LiveData的问题如何解决?下面主要结合日常开发的经验,给出你关于Android 协程和 LiveData的解决方法建议,希望对你解决Android 协程和 LiveData有所启发或帮助;

我想知道我必须在 AndroID 应用程序上使用 CoroutInes 和 liveData 的代码是否正确,或者是否有问题。

以一个 UserProfile 片段和一个 EditUserBio 片段为例。我有一个 UserProfileviewmodel 范围到这 2 个片段。

我的 UserProfileviewmodel 类似于:

class UserProfileviewmodel : viewmodel() {
    private val _loading = mutablelivedata<Boolean>()
    val loading: liveData<Boolean> get() = _loading

    private val _errormessage = mutablelivedata<String>()
    val errormessage: liveData<String> get() = _errormessage
    
    private val _user = mutablelivedata<User>()
    val user: liveData<User> get() = _user
...
}

在 UserProfileFragment 和 EditUserBioFragment 中,我观察 loadingerrormessage liveData 事件以显示加载对话框和错误消息

在 EditUserBioFragment 中,我希望能够点击一个按钮,进行网络调用以更新用户配置文件,更新缓存的用户,然后返回到 UserProfileFragment。

根据我对 Use Kotlin coroutInes with Architecture components 和 cortoutInes LiveData 的理解,我可以执行以下操作:

viewmodel.updateBio(data).observe(vIEwlifecycle@R_674_11125@r,{
    Navigation.findNavController(v).popBACkStack()
})

我的 UserProfileviewmodel 实现类似于

fun updateBio(profile: UserProfileModel) = liveData {
    withContext(viewmodelScope.coroutIneContext) {
        _loading.postValue(true)
        try {
            /* suspend*/ userRepository.updateProfile(profilE)
            emit(VoID.TYPE)
        } catch (e : Exception) {
            _errormessage.postValue(e.localizedmessagE)
        } finally {
            _loading.postValue(false)
        }
    }
}

这是正确的用法吗?

如果 userRepository.updateProfile(profilE) 抛出是否有问题:

  1. 没有打电话给emit
  2. 还是多次调用 viewmodel.updateBio(data).observe(

解决方法

我建议你看看coroutInes best practices by Google。

我不会(从 UI/Fragment/Activity)viewModel.someOperation(xxX).observe(...) 一直这样做,我认为这会使代码更难遵循。您已经公开了所有这些 LiveData,并且必须确保事情发生在正确的流中。

我会改为使用一个(如果您想拆分“导航”,也可以使用两个)状态:

viewModel.state.observe(viewLifecycle@R_674_11125@r) { state ->
            when (statE) {
              is X -> ...
              is Y -> ...
  

你懂的。

在您的虚拟机中,“状态”就是您的猜测:

    private val _state = MutableLiveData<SomeState>(SomeState.DefaultStatE)
    val state: LiveData<SomeState> = _state

这使 UI(片段/行为)与必须处理协程、响应等的逻辑分离。相反,您现在在 ViewModel 内完成所有这些工作,这将“额外一英里”检查发生了什么,并发出一个明智的/固执的“SomeState”,片段可以对此做出反应。

所以你的 updateBio 乐趣变得更多..

fun updateBio(profile: UserProfileModel) {
     viewModelScope.launch {
         _state.postValue(SomeState.Loading)

         // here call your useCase/Repo/etc. which is suspend.
         // evaluate the response,wait for it,do what it takes,and .postValue(SomeState.XXX) based on your logic. 

现在 userRepository.updateProfile(profilE) 可以返回一个具体的类型,比如直接返回新更新的 Profile 或者它可以公开具有各种“状态”的 sealed class UserProfileState {}便 ViewModel :

sealed class UserProfileState {
   data class updatedOk(val profile: UserProfileModel) : UserProfileState()
   data class Failure(val exception: Exception) : UserProfileState()
}

然后你会...

when (val response = userRepo.update(profilE)) {
    is UserProfileState.updatedOk -> _state.postValue(SomeState.updated(response.profilE))
    is Failure -> //deal with it
}

我希望你能明白。最后,如果 userProfile 无法更新 bio,如果您使用“UserProfileState”,您可以用 .Failure 发出信号。或者,如果它只返回“UserProfileModel”,您必须决定是要引发异常还是返回 Null 并让 ViewModel 决定要做什么。这真的取决于你需要什么样的互动。

,

我确实发现了 ViewModel 的范围问题。

我最终创建了一个

sealed class LiveDataResult<out R> {
    data class Loading(val show: Boolean) : LiveDataResult<Nothing>()
    data class Result<out T>(val value: T) : LiveDataResult<T>()
    data class Error(val message: String?) : LiveDataResult<Nothing>()
}

并更改 updateBio 以发出 LiveDataResult

fun updateBio(profile: updateProfilerequestModel) = liveData {
    withContext(viewModelScope.coroutIneContext) {
        emit(LiveDataResult.Loading(true))
        try {
            userRepository.updateProfile(profilE)
            emit(LiveDataResult.Result(true))
        } catch (e : Exception) {
            emit(LiveDataResult.Error(e.localizedmessagE))
        } finally {
            emit(LiveDataResult.Loading(false))
        }
    }
}

对于多个调用,我想这是比单个 val loading: LiveData<Boolean>val errormessage: LiveData<String> 更好的解决方案。

大佬总结

以上是大佬教程为你收集整理的Android 协程和 LiveData全部内容,希望文章能够帮你解决Android 协程和 LiveData所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:协程和