Intereting Posts
Google Espresso: удалять данные пользователя по каждому тесту Неразрешенная ссылка: sun.misc.MessageUtils.where RX2.0 вложенная обработка ошибок подписки Использование объекта-компаньона для возврата экземпляра класса в Котлин Ошибка: выполнение выполнено для задачи ': app: kaptDebugKotlin' Firebase неразрешенный супертип с Kotlin на Android Использование расширений ресурсов Google для Kotlin с использованием только Maven как запустить скомпилированный файл класса в Котлине? Как класс макета может не соответствовать его классу java в Котлине? Как позволить классу данных реализовать интерфейс / расширяет свойства суперкласса в Котлине? Почему у Kotlin есть два синтаксиса для lambdas / анонимных функций? IDEA показывает проект дважды в дереве Как представить таблицу соединений с дополнительным полем с помощью eBean и Kotlin? Внутренняя функция покрытия кода Ссылка на набор свойств класса Kotlin как функция

Чистая архитектура: ViewModel с несколькими UseCases на Android

Это скорее вопрос архитектуры, чем исправление ошибки.

Предположим, что это приложение позволяет пользователям отмечать Bus и / или Bus Station в качестве фаворита. Мой вопрос в том, должен ли я иметь ViewModel с использованием UseCases или должен ли я использовать UseCase, который инкапсулирует текущую логику?

Также для части вопроса я не совсем уверен, каким образом я должен предоставить объединенные данные на уровне пользовательского интерфейса (см. 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 так как в настоящее время я не уверен, что это правильный путь;).

Solutions Collecting From Web of "Чистая архитектура: ViewModel с несколькими UseCases на Android"

Вся точка ViewModel заключается в том, что она является моделью того, что использует вид. Он должен быть как можно ближе к нему. Если вы не представляете станции и автобусы в одном списке (кажется уродливым), в противном случае они представляют собой отдельные виды и должны иметь отдельные модели.

В идеале ViewModel будет иметь только представление для своего представления. Используя MediatorLiveData, вы можете объединить все источники состояния в единицу, которая представляет состояние представления с течением времени.

То, что вы можете иметь, – это класс данных, который представляет ваш ViewState, который вы создаете на своей модели просмотра, и является вашей открытой LiveData

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

Однако вы знаете, зависит от ViewModel, чтобы построить окончательный ViewState, который как бы нарушает принцип единой ответственности, а также делает вас зависимым от платформы Android.

Я бы подошел к нему, используя составной UseCase, в котором были как случаи использования станций, так и шины, и возвращает собранные данные, которые затем можно легко вывести из ViewModel.