【问题标题】:Clean Architecture: ViewModel with multiple UseCases on Android清洁架构:Android 上具有多个用例的 ViewModel
【发布时间】:2018-04-24 13:25:41
【问题描述】:

这更像是一个架构问题,而不是一个错误修复问题。

假设此应用允许用户将巴士和/或巴士站标记为收藏。我的问题是,我应该有两个 UseCases 的 ViewModel 还是应该构建一个封装当前逻辑的 UseCase?

对于问题部分,我不完全确定应该将组合数据暴露给 UI 层的方式(请参阅favouritesExposedLiveData

提前感谢任何反馈,这是我的ViewModel,您可以假设每个用例都从数据源传递正确的数据。

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,因为此时,我不确定这是正确的方法;)。

【问题讨论】:

    标签: android mvvm architecture kotlin viewmodel


    【解决方案1】:

    ViewModel 的全部意义在于它是视图使用的模型。它应该尽可能接近。除非您在同一个视图列表中显示车站和公共汽车(看起来很难看),否则它们是单独的视图,并且应该得到单独的模型。

    【讨论】:

    • 感谢您的反馈,但您并没有真正回答问题,是的,我想同时显示 Buses 和 Stations(标记为收藏夹)。
    【解决方案2】:

    理想情况下,ViewModel 仅具有其视图的视图状态。通过使用 MediatorLiveData,您可以将所有状态源聚合为一个表示一段时间内的视图状态。

    您可以拥有一个数据类,它代表您在视图模型上构建的 ViewState,并且是您公开的 LiveData

    data class FavouritesViewState(val favoriteStations: List&lt;Station&gt;, val favoritBuses: List&lt;Bus&gt;)

    但是你知道依赖 ViewModel 来构造最终的 ViewState,这有点违反单一责任原则,也让你依赖于一个 Android 框架。

    我将使用具有车站和公共汽车用例的复合 UseCase 来处理它,并返回组合数据,然后您可以轻松地从 ViewModel 公开这些数据。

    【讨论】:

      猜你喜欢
      • 2022-05-18
      • 1970-01-01
      • 1970-01-01
      • 2021-10-16
      • 2017-03-20
      • 2020-03-02
      • 2018-06-15
      • 1970-01-01
      • 2022-10-23
      相关资源
      最近更新 更多