这更像是一个架构问题,而不是修复它的错误。
我们假设此应用程序允许用户将总线和/或总线站标记为收藏夹。我的问题是,我应该使用两个UseCases ViewModel
还是应该构建一个封装当前逻辑的UseCase?
同样对于问题部分,我不完全确定将组合数据暴露给UI层的方式(参见favouritesExposedLiveData
)
在此先感谢任何反馈,欢迎来到我的ViewModel
,您可以假设每个UseCase都从数据源传递正确的数据。
open class FavouritesViewModel @Inject internal constructor(
private val getFavouriteStationsUseCase: GetFavouriteStationsUseCase,
private val getFavouriteBusesUseCase: GetFavouriteBusesUseCase,
private val favouriteMapper: FavouriteMapper,
private val busMapper: BusMapper,
private val stationMapper: StationMapper) : ViewModel() {
private val favouriteBusesLiveData: MutableLiveData<Resource<List<BusView>>> = MutableLiveData()
private val favouriteStationsLiveData: MutableLiveData<Resource<List<StationView>>> = MutableLiveData()
private lateinit var favouritesMediatorLiveData: MediatorLiveData<List<FavouriteView>>
private lateinit var favouritesExposedLiveData: LiveData<Resource<List<FavouriteView>>>
init {
fetchFavourites()
}
override fun onCleared() {
getFavouriteStationsUseCase.dispose()
getFavouriteBusesUseCase.dispose()
super.onCleared()
}
fun getFavourites(): LiveData<Resource<List<FavouriteView>>> {
return favouritesExposedLiveData
}
private fun fetchFavourites() {
favouritesMediatorLiveData.addSource(favouriteStationsLiveData, { favouriteStationListResource ->
if (favouriteStationListResource?.status == ResourceState.SUCCESS) {
favouriteStationListResource.data?.map {
favouriteMapper.mapFromView(it)
}
}
})
favouritesMediatorLiveData.addSource(favouriteBusesLiveData, { favouriteBusesListResource ->
if (favouriteBusesListResource?.status == ResourceState.SUCCESS) {
favouriteBusesListResource.data?.map {
favouriteMapper.mapFromView(it)
}
}
})
getFavouriteStationsUseCase.execute(FavouriteStationsSubscriber())
getFavouriteBusesUseCase.execute(FavouriteBusesSubscriber())
}
inner class FavouriteStationsSubscriber : DisposableSubscriber<List<Station>>() {
override fun onComplete() {}
override fun onNext(t: List<Station>) {
favouriteStationsLiveData.postValue(Resource(ResourceState.SUCCESS, t.map { stationMapper.mapToView(it) }, null))
}
override fun onError(exception: Throwable) {
favouriteStationsLiveData.postValue(Resource(ResourceState.ERROR, null, exception.message))
}
}
inner class FavouriteBusesSubscriber : DisposableSubscriber<List<Bus>>() {
override fun onComplete() {}
override fun onNext(t: List<Bus>) {
favouriteBusesLiveData.postValue(Resource(ResourceState.SUCCESS, t.map { busMapper.mapToView(it) }, null))
}
override fun onError(exception: Throwable) {
favouriteBusesLiveData.postValue(Resource(ResourceState.ERROR, null, exception.message))
}
}
}
注意:目前MediatorLiveData
(favouritesMediatorLiveData
)没有将数据绑定回favouritesExposedLiveData
,因为此时我不确定这个是正确的方法;)。
答案 0 :(得分:1)
理想情况下,ViewModel只能为其视图提供视图状态。通过使用MediatorLiveData,您可以将所有状态源聚合为一个表示视图状态的状态源。
您可以拥有的是一个数据类,它代表您在视图模型上构建的ViewState,并且是您公开的LiveData
data class FavouritesViewState(val favoriteStations: List<Station>, val favoritBuses: List<Bus>)
但是你知道依赖于ViewModel来构造最终的ViewState,这有点打破了单一责任原则,也让你依赖于Android框架。
我会使用具有工作站和总线用例的复合UseCase来处理它,并返回组合数据,然后您可以从ViewModel轻松公开。
答案 1 :(得分:0)
ViewModel的重点在于它是视图所使用的模型。它应该尽可能接近。除非你在相同的视图列表中显示站点和总线(看起来很难看),否则,它们是单独的视图,并且应该得到单独的模型。