Вопросы об ответственности каждого компонента в компонентах архитектуры Android - PullRequest
8 голосов
/ 19 апреля 2019

Я давно использую MVP и начинаю переходить в гибридное состояние между MVP и MVVM

Подробно мои приложения будут выглядеть так:

  • Каждое действие имеет от 0 до x фрагментов, которые представляют его взгляды
  • Каждый фрагмент запрашивает ViewModel действия, чтобы они могли получить данные, используя LiveData
  • Деятельность будет иметь отдельную ViewModel, которая будет выступать в качестве докладчика. При создании этого ViewModel будет добавлен ViewModel действия с LiveData, чтобы он мог обновлять пользовательский интерфейс при необходимости
  • Докладчик получит сообщения, отправленные на ViewModel данных, и отправит результаты обратно на него

Мои вопросы:

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

Например, допустим, у меня есть список элементов, и пользователь долго нажимает один, чтобы отредактировать их, какая часть этой архитектуры должна отвечать за проверку, есть ли у пользователя разрешение на это, и позволяет ли он редактировать элемент или показать сообщение об ошибке?

  1. Есть ли у Фрагментов способ получить только часть ViewModel Действия?

Например, если предположить, что у действия есть 3 фрагмента и одна модель представления для обслуживания

Могу ли я использовать что-то вроде:

class MainViewModel : ViewModel() , IFragmentA, IFragmentB, IFragmentC

и затем, когда я пытаюсь получить ViewModel во фрагментах, я могу написать что-то вроде:

lateinit var viewModel: IFragmentA

override fun onAttach(context: Context?) {
    super.onAttach(context)
    vm = ViewModelProviders.of(context as AppCompatActivity).get(IFragmentA::class.java)
}

примечание: я знаю, что вышеприведенный код не работает, я спрашиваю, есть ли способ, чтобы что-то подобное могло работать

  1. Является ли правильный способ отправки сообщений обратно в активность SingleEvents?

Например, если пользователь пытается удалить запись, и я хочу, чтобы он ввел пароль, поток будет:

  • Фрагмент отправляет сообщение для удаления на свою ViewModel
  • ViewModel передает его докладчику
  • Ведущий решает, что ему нужно подтвердить пароль перед тем, как продолжить
  • Докладчик устанавливает значение SingleEvent в ViewModel
  • ViewModel уведомляет подписчиков события (в данном случае MainActivity), что они должны показать диалоговое окно с запросом пароля

Спасибо за любую помощь, которую вы можете оказать

1 Ответ

4 голосов
/ 24 апреля 2019

Я недавно перенес одно приложение из архитектуры MVP в архитектуру MVVM. не имеет значения, делаете ли вы это частично или полностью, вы движетесь к чему-то великому и чистому, и вам это понравится.

Прежде чем проверять ответ, пожалуйста, взгляните на эту диаграмму архитектуры MVVM и некоторые из ее достоинств и недостатков

MVVM Architecture

Давайте посмотрим на роли каждого класса здесь.

Деятельность / Fragment:

-Слушать MubeLiveData Obeservers и установить данные для представлений, никакой другой логики здесь.

ViewModel

  • Проверка ввода пользователя (проверка имени пользователя, пароля пустая или проверка на ноль)
  • установить свой mutableLive
  • попросить репозиторий запустить сетевую задачу или локальное хранилище данных (sqlite) с обратными вызовами.

Репозиторий

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

RemoteDataSource

  • выполняет сетевой вызов и возвращает полученные данные обратно в хранилище.

LocalDataSource

  • обрабатывает все, что связано с SQLite, и передает запрошенные данные с помощью обратных вызовов.

есть пример проекта приложения todo от google , который использует MVVM. Пожалуйста, обратитесь, это будет очень полезно.

  1. Нет докладчика - проверьте пользовательские входные данные на viewmodel и общайтесь через репозиторий и обратно, используя MutableLiveData.
  2. Делайте свою бизнес-логику в репозитории, рассматривайте ее больше как модель в шаблоне mvp.
  3. У вас может быть одна viewModel для вашей деятельности и ее фрагментов. Все ваши фрагменты общаются через одну viewModel. Таким образом, каждый фрагмент будет реагировать только на LiveDataObserver, который он слушает.

На самом деле есть пример этого варианта использования в примере проекта Google для MVVM.

AddEditTaskActivity.java

public static AddEditTaskViewModel obtainViewModel(FragmentActivity activity) {
       // Use a Factory to inject dependencies into the ViewModel        
 ViewModelFactoryfactory= ViewModelFactory.getInstance(activity.getApplication());
 return ViewModelProviders.of(activity, factory).get(AddEditTaskViewModel.class);
   }

AddEditTaskFragment.java

 @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        final View root = inflater.inflate(R.layout.addtask_frag, container, false);
        if (mViewDataBinding == null) {
            mViewDataBinding = AddtaskFragBinding.bind(root);
        }

        mViewModel = AddEditTaskActivity.obtainViewModel(getActivity());

        mViewDataBinding.setViewmodel(mViewModel);
        mViewDataBinding.setLifecycleOwner(getActivity());

        setHasOptionsMenu(true);
        setRetainInstance(false);

        return mViewDataBinding.getRoot();
    }

  1. Поток проверки пароля:
    • фрагмент просит ViewModel удалить Entry.
    • Попросите хранилище решить, нужна ли проверка, с данными, которые у нас уже есть, или для связи с локальным источником данных.
    • ViewModel получает обратный вызов из репозитория с сообщением о необходимости проверки, ViewModel обновляет соответствующий MutableLiveData showVerification.postValue (true);
    • Когда действие прослушивает showVerificationObserver, оно отображает интерфейс проверки.

Надеюсь, это поможет.

...