大佬教程收集整理的这篇文章主要介绍了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 中,我观察 loading
和 errormessage
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)
抛出是否有问题:
我建议你看看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”,片段可以对此做出反应。
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,请注明来意。