2017-11-11 18 views
0

これは、バグを修正するよりもアーキテクチャ上の問題です。クリーンなアーキテクチャ:Androidで複数のユースケースを持つViewModel

このアプリでは、ユーザーがBusステーションやBusステーションをお気に入りとしてマークすることができます。私の質問は、両方の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)) 
      } 

     } 
    } 

注:;)この時点で、私はこれは行くための正しい方法であるか分からないので、現在MediatorLiveDatafavouritesMediatorLiveDataは)戻ってfavouritesExposedLiveDataにデータをバインドされていません。

答えて

0

ViewModelの全体点は、ビューが使用しているもののモデルであるということです。それは可能な限り近いものでなければなりません。ステーションとバスを同じビューリスト(見苦しいようです)で提示しない限り、別々のビューであり、別々のモデルを取得する必要があります。

+0

あなたのご意見ありがとうございますが、実際に質問に答えているわけではありません。はい、私はバスとステーションの両方を表示したいと思っています。 –

0

理想的には、ViewModelは、そのビューのビューステートのみを持つことが理想的です。 MediatorLiveDataを使用すると、すべての状態のソースを時間の経過とともにビューの状態を表すものに集約できます。あなたが最終的にViewStateどれを構築するためのViewModelに依存知っているしかし、あなたが持つことができる何

はあなたのビューモデルに構築あなたのViewStateを表すデータクラスであり、あなたの暴露LiveData

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

です一種の責任原則が破られ、Androidフレームワークに依存することにもなります。

私は、ステーションとバスの両方のユースケースを持ち、ViewModelから簡単に公開できる合成データを返す複合ユースケースを使用してアプローチします。

関連する問題