我已经根据最新的 Google 架构指南开发了示例项目,
我有一个 fragment 。
MainFragment.kt
- 从
MainViewModel
接收数据LiveData
并更新运行良好的 UI
MainViewModel.kt
- 有
MutableLiveData<User>
用户,每当我更新用户时,我的观察者在MainFragment
接到电话,我正在更新 UI(工作正常)
现在我的问题是?
在我的
MainActivity
我加载了两个 fragment ,MainFragment
&SecondaryFragment
.- 我有一个 Repository.kt 类,它进行 API 调用并从
SecondFragment.KT
获取用户数据
- 我有一个 Repository.kt 类,它进行 API 调用并从
现在如何从 Repository.kt 通知 MainViewModel 我有最新数据要更新?
- 我需要使用
RXJava
吗?从Repository.KT
传递数据至MainViewModel.KT
,那么我该如何使用它来传递用户数据呢? - Android 最新架构是否支持任何观察者完成此任务?
最佳答案
让我们分部分来:
Now how do I notify from Repository.kt to MainViewModel that I have latest data to update ?
您可以使用观察者模式,就像您从 MainViewModel 到 UI 使用的模式一样。如果你使用改造,你可以使用调用适配器从你的改造调用中返回 RxJava 的 Observables(或 Singles,Flowables 等等),所以例如你可以有这样的东西:
@Headers({"Content-Type: application/json", "Accept: application/json"})
@POST("/sign_in")
Single<Response<LoginResponse>> traditionalLoginUser(
@Body LoginRequest request,
@Header("Authorization") String authToken);
这是一个典型的 Retrofit 接口(interface),它返回一个 Single,然后您可以在您的存储库中观察这个 Single 或简单地将它传递给 ViewModel 以在那里观察。
您还可以为 LiveData 添加一个调用适配器(google 实现了一个 here )并使用 LiveData 而不是 RxJava。不过,我个人不喜欢在网络层使用 LiveData。
do I need to use RXJava to pass the data from Repository.KT to MainViewModel.KT, in that case how do I use it to pass user data?
你可以使用 RxJava,是的。实际上,我一直在开发一个完全可以做到这一点的示例应用程序。基本思想是您使用存储库从 API 获取数据并将 Observable 传递给 ViewModel。我喜欢在 ViewModel 中做的是通过订阅其中的可观察对象(或其他 rx 实体)并接收数据来处理任何可能的错误。由于我们不一定像处理 RxJava 那样处理 LiveData 上的错误,我们可以包装 LiveData 以将错误传播到 View 作为我们包装器的状态(这实际上可以在这个 google sample 中找到)。
例如,在我的存储库中我有这个:
fun getUsersNotPaged(page: Int, pageSize: Int): Single<SOResponse<User>> {
return remoteDataSource.apiService.getTopUsers(page, pageSize)
}
然后在我的 View 模型中我这样做:
var userList: MutableLiveData<LiveResource<SOResponse<User>>> = MutableLiveData()
fun getUserListNotPaged(page: Int, pageSize: Int): MutableLiveData<LiveResource<SOResponse<User>>> {
val result = usersRepository
.getUsersNotPaged(page, pageSize)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ result ->
userList.postValue(LiveResource(LiveResourceStatus.SUCCESS, result, null))
}, { error ->
userList.postValue(LiveResource(LiveResourceStatus.ERROR, null, error.localizedMessage))
})
return userList
}
在我看来:
viewModel.getUserListNotPaged(1, 20).observe(this, Observer {
it?.data?.let {
Toast.makeText(this.context, "Here", Toast.LENGTH_SHORT).show()
}
})
我使用 LiveResource 来包装我的 RxJava 响应和错误。
您还可以使用 ReactiveStrems
扩展将 Rx Publisher
转换为 LiveData
,但您需要处理错误时的情况发生在 ViewModel
中,并保证生成的 LiveData
没有错误。像这样:
fun getUserListNotPaged(page: Int, pageSize: Int): LiveData<SOResponse<User>> {
val result = usersRepository
.getUsersNotPaged(page, pageSize)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.onErrorReturn {
SOResponse<User>()
}
.toFlowable()
return LiveDataReactiveStreams.fromPublisher(result)
}
在这种情况下,每当出现错误时,我都会返回一个空响应。
Does Android Latest Architecture do support any observer to accomplish this?
是的,如您所见,您可以在整个过程中的所有地方或仅在过程中使用 LiveData
(仅从 VM 到 UI)。有些人不同意在 HTTP 调用中使用 LiveData
though (我是其中之一,哈哈)。
关于android - 关于谷歌最新架构指南的 MVVM 模式,如何将数据(通知)从存储库类传递到模型 View 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50618369/