Повторное использование ViewModels - укажите для каждого экрана, который будет его использовать - PullRequest
1 голос
/ 10 июня 2019

Согласно этой статье :

Модель представления должна представлять состояния для представления, а не только для событий.

Я использую повторноviewmodel, потому что мне нужны одни и те же данные для нескольких представлений , но я сомневаюсь, что они используют одни и те же данные, но отображают их по-разному .Как, например, если у меня есть список пользователей, в первом представлении отображаются их , во втором представлении используются данные для целей сортировки , в третьем представлении отображается метка , если список пользователей достиг определенного размера .

Если я только выставляю данные (список пользователей), и представление решает, что делатьэто, кроме того, что я нарушаю архитектуру, это также трудно проверить, потому что мне нужно смоделировать android, но я хочу только проверить, вызывается ли определенный метод, не имеет значения, как его отображает представление.

Так что я думаю о решении, как о создании класса State для каждого представления, которое использует модель представления, чтобы модель представления обновляла состояние, и теперь я могу легко проверить, изменяется ли состояние.

Моя проблема здесьчем больше представлений повторно использует модель представления, тем больше состояний для каждого вида, мне это тоже не кажется правильным, просто представьте, как метод изменяет все состояния, даже если одновременно может отображаться только 1 представление.

Создание отдельных моделей представления для каждого представления похоже на дублирование кода для меня, например: ResetPasswordView и CreatePasswordView, они оба имеют одинаковый процесс, почти одинаковое поведение, так почему бы не использовать повторно Viewmodel?... или я должен?Что мне здесь не хватает?

Редактировать (мое текущее решение):

Из того, что я сделал, я создал отдельные модели представления для каждого фрагмента / действия, потому что хотя они используют одни и те же данные, они представляют их по-разному .И, делая это, я могу выполнять модульные тесты для логики представления, потому что все манипуляции с данными (особенно для представления) происходят в модели представления.

Я делюсь моделью представления, но для целей навигации, пример - лучший способ объяснить это (я использую Koin здесь в качестве моей структуры зависимостей):

OnBoardingActivity :

class OnBoardingActivity {

   var fullNameViewModel by viewModel<FullNameViewModel>()

   private fun initViewModels() {
      fullNameViewModel.stateShowEmail.observe(this, Observer {
         // do navigate to email because that's the next screen/fragment after FullNameFragment
      })
   }
}

FullNameFragment :

class FullNameFragment {

   var viewModel by sharedViewModel<FullNameViewModel>() // notice that I share the view model from the activity here to have only 1 instance

   private fun initViews() {
      RxTextView.textChanges(etFirstName)
         .doOnNext { viewModel.setFirstName(it.toString()) }
         .subscribe()

     // ... set the other fields
   }

   private fun initViewModels() {
      viewModel.stateValidationFirstName.observe(this, Observer {
         when(it) { // validation
            is RequiredValidation -> // show some error/validation message
            else -> it is valid! remove any error/validation messages
         }
      })
   }
}

FullNameViewModel :

class FullNameViewModel {

   val stateValidationFirstName = MutableLiveData<Validation>() // some validation object
   val stateShowEmail = SingleLiveEvent<Any>() // I'm using the hacky single live event here hehe

   fun setFullName() {
      // do the validations, some process and this can be easily test
      // like: stateValidationFirstName = RequiredValidation()

      stateShowEmail.call()
   }
}

1 Ответ

1 голос
/ 18 июня 2019

Как правило, когда статья ссылается на представление, они не означают буквальный класс View. Они имеют в виду это в архитектурном смысле.

Возьми MVVM. Model-View-ViewModel.

Когда мы говорим об Android, View - это макет Activity, Fragment и View.

Так что в идеале у вас должен быть один ViewModel для большинства логических наборов.

Если у вас есть Activity и макет, но нет Fragment, то имеет смысл иметь один ViewModel для покрытия состояния Activity, включая его макет.

Если у вас есть Activity с собственным макетом И Fragment, то у вас может быть два ViewModel с. Один для состояния Activity и один для Fragment.

Я написал пример приложения, которое может помочь: https://github.com/DavidEdwards/mvvm-example

Возьмите пример наличия базового Activity без макета, за исключением его Fragment. У вас будет один ViewModel в Fragment (обычно это ни в коем случае не правило). В этом ViewModel у вас будет LiveData, представляющий состояние ваших View s. Когда вы хотите изменить состояние View, вы изменяете состояние в ViewModel, и ViewModel распространяет изменения на View. Обычно я выполняю это, передавая ViewModel в мои макеты, используя превосходную библиотеку Android Databindings Library .

Вы можете увидеть пример этого здесь , здесь и здесь . В этом примере я контролирую видимость View, наблюдая за количеством игроков в игре.

...