2017-11-11 124 views
0

這是一個架構問題,而不是一個修復問題的問題。乾淨的體系結構:在Android上有多個UseCases的ViewModel

讓我們假設這個應用程序允許用戶將公共汽車和/或巴士站標記爲收藏夾。我的問題是,如果我有一個ViewModel兩個UseCases或我應該建立一個封裝當前邏輯的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)) 
      } 

     } 
    } 

注:目前MediatorLiveDatafavouritesMediatorLiveData)沒有在這個時候數據綁定回favouritesExposedLiveData,因爲,我不知道這是要走正確的方式)。

回答

0

ViewModel的重點在於它是視圖使用的模型。它應該儘可能接近。除非你在同一個視圖列表中顯示車站和公共汽車(否則),否則,它們是單獨的視圖,應該有不同的模型。

+0

感謝您的反饋,但您並未真正回答這個問題,是的,我想同時顯示巴士和車站(標記爲收藏夾)。 –

0

理想情況下,一個ViewModel只能有其視圖的視圖狀態。通過使用MediatorLiveData,您可以將所有狀態來源聚合爲代表隨時間變化的視圖狀態。

什麼你可以是代表你的瀏覽狀態,你建立你的視圖模型,併爲您的暴露LiveData

data class FavouritesViewState(val favoriteStations: List<Station>, val favoritBuses: List<Bus>)

但是你知道取決於視圖模型來構建最終的ViewState數據類有點打破單一責任原則,也讓你依賴於Android框架。

我會使用具有工作站和總線用例的複合UseCase來處理它,並返回可從ViewModel輕鬆公開的組合數據。