Структура mvvm проекта папки android

Шаблон дизайна Android MVVM

Android MVVM, шаблон представления модели Android, шаблон MVVM для Android, пример mvvm для Android, шаблоны проектирования android, учебник по MVVM для Android, пример кода шаблона MVVM для Android.

Автор: Pankaj Kumar
Дата записи

В этом уроке мы обсудим и реализуем архитектурный шаблон Android MVVM в нашем приложении для Android. Ранее мы обсуждали шаблон MVP для Android .

Android MVVM

MVVM означает Модель , Представление , Модель представления .

  • Модель : Здесь хранятся данные приложения. Он не может напрямую общаться с Видом. Как правило, рекомендуется предоставлять данные модели представления с помощью наблюдаемых объектов.
  • Вид : Он представляет пользовательский интерфейс приложения, лишенный какой-либо логики приложения. Он наблюдает за моделью представления.
  • ViewModel : Он действует как связующее звено между Моделью и Представлением. Он отвечает за преобразование данных из модели. Он предоставляет потоки данных для представления. Он также использует крючки или обратные вызовы для обновления представления. Он запросит данные из модели.

Следующий поток иллюстрирует основной шаблон MVVM.

Чем это отличается от MVP?

  • ViewModel заменяет докладчика в Среднем слое.
  • Ведущий содержит ссылки на Представление. Модель представления этого не делает.
  • Ведущий обновляет представление классическим способом (методы запуска).
  • Модель представления отправляет потоки данных.
  • Ведущий и представление находятся в соотношении 1 к 1.
  • Представление и модель представления находятся в соотношении 1 ко многим.
  • Модель представления не знает, что представление прослушивает ее.

Существует два способа реализации MVVM в Android:

В этом уроке мы будем использовать только привязку данных. Библиотека привязки данных была введена Google для привязки данных непосредственно в xml-макете. Для получения дополнительной информации о привязке данных обратитесь к этому учебному пособию.

Мы создадим пример приложения для простой страницы входа, которое запрашивает ввод данных пользователем. Мы увидим, как модель представления уведомляет Представление о том, когда показывать всплывающее сообщение, не сохраняя ссылку на представление.

Как можно уведомить какой-либо класс, не имея на него ссылки?

Это можно сделать тремя различными способами:

  • Использование Двусторонней Привязки Данных
  • Использование Живых Данных
  • Использование RxJava

Двусторонняя Привязка Данных

Двусторонняя привязка данных-это метод привязки ваших объектов к вашим XML-макетам таким образом, чтобы объект и макет могли отправлять данные друг другу.

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

Для этого нам нужен Адаптер привязки и пользовательский атрибут, определенный в XML.

Адаптер привязки будет прослушивать изменения в свойстве атрибута.

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

Пример структуры проекта Android MVVM

Добавление библиотеки привязки данных

Добавьте следующий код в файл build.gradle вашего приложения:

Это позволяет привязывать данные в вашем приложении.

Добавление зависимостей

Добавьте следующие зависимости в свой файл build.gradle :

Модель

Модель будет содержать адрес электронной почты и пароль пользователя. Следующее User.java класс делает это:

Двусторонняя привязка данных позволяет нам связывать объекты в XML-макетах таким образом, чтобы объект мог отправлять данные в макет и наоборот.

Синтаксис двусторонней привязки данных @=

Расположение

Код для activity_main.xml приводится ниже:

Привязка данных требует, чтобы мы установили тег макета вверху. Здесь наша модель представления привязывает данные к представлению. ()-> ViewModel.onLoginClicked() вызывает лямбду прослушивателя щелчка кнопки, определенную в нашей модели просмотра. Текст редактирования обновляет значения в модели (через Модель представления).

привязка:toastMessage=»@» -это пользовательский атрибут, который мы создали для двусторонней привязки данных. На основе изменений в сообщении тоста в модели представления адаптер привязки будет активирован в представлении.

Модель представления

Код для LoginViewModel.java приводится ниже:

Методы, которые были вызваны в макете, реализованы в приведенном выше коде с той же подписью. Если XML-аналог метода не существует, нам нужно изменить атрибут на app: .

Приведенный выше класс также может расширять ViewModel. Но нам нужна базовая наблюдаемость, так как она преобразует данные в потоки и уведомляет об изменении свойства всплывающее сообщение .

Нам нужно определить получатель и установщик для пользовательского атрибута тостового сообщения, определенного в XML. Внутри сеттера мы уведомляем наблюдателя (который будет отображаться в нашем приложении) о том, что данные изменились. Представление(Наша деятельность) может определить соответствующее действие.

Код для MainActivity.java класс приведен ниже:

Благодаря привязке данных класс ActivityMainBinding автоматически генерируется из макета. Метод @BindingAdapter запускается всякий раз, когда изменяется атрибут всплывающего сообщения, определенный на Кнопке. Он должен использовать тот же атрибут, что определен в XML и в модели представления.

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

Результаты приведенного выше приложения в действии приведены ниже:

На этом заканчивается этот учебник по Android MVVM с использованием привязки данных. Вы можете скачать проект по ссылке, приведенной ниже.

Источник

MVVM на Android с компонентами архитектуры + библиотека Koin

Jan 13, 2020 · 7 min read

Введение

С MVVM ( Model— View-ViewModel) процесс разработки графического интерфейса для пользователей делится н а две части. Первая — это работа с языком разметки или кодом GUI. Вторая — разработка бизнес-логики или логики бэкенда (модель данных). Часть V iew model в MVVM — это конвертер значений. Это значит, что view model отвечает за конвертирование объектов данных из модели в такой вид, чтобы с объектами было легко работать. Если смотреть с этой стороны, то view model — это скорее модель, чем представление. Она контролирует большую часть логики отображения. Модель представления может реализовывать паттерн медиатор. Для этого организуется доступ к логике бэкенда вокруг набора юз-кейсов, поддерживаемых представлением.

В этом туториале мы попробуем определить каждый компонент паттерна MVVM, чтобы создать небольшое приложение на Android в соответствии с ним.

На следующей картинке — разные элементы, которые мы собираемся создать при помощи компонента Architecture и библиотеки Koin для внедрения зависимостей.

Архитектуру ниже можно разделить на три различные части.

Представление

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

Читайте также:  Режим recovery android как войти

Модель представления

Этот компонент связывает модель и представление. Отвечает за управление ссылками данных и возможных конверсий. Здесь появляется биндинг. В Android мы не беспокоимся об этом, потому что можно напрямую использовать класс AndroidViewModel или ViewModel.

Модель

Это уровень бизнес-данных и он не связан ни с каким особенным графическим представлением. В Android, согласно “чистой” архитектуре, модель может содержать базу данных, репозиторий и класс бизнес-логики. Картинка ниже описывает взаимодействие между разными компонентами.

Как реализовать паттерн MVVM

Чтобы реализовать паттерн MVVM, важно начать с компонентов, которым для работы нужен другой компонент. Это и есть зависимость.

А с момента появления компонента архитектуры, логичное общее решение — реализовать Android-приложения при помощи модели с изображения ниже. Там вы увидите стрелки, которые ведут от представления (активности/фрагмента) к модели.

А это значит, что View знает о View-Model, а не наоборот, и View Model знает о Model, и не наоборот. То есть у представления будет связь с моделью представления, а у модели представления будет связь с моделью. Строго в таком порядке, никак иначе. Благодаря такой архитектуре приложение легко поддерживать и тестировать.

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

Сценарий приложения и реализация модели

Чтобы понять, как функционирует паттерн MVVM, мы напишем небольшое приложение, в котором будут все компоненты с предыдущей картинки. Мы создадим программу, которая покажет данные. Мы их взяли по этой ссылке. Приложение будет сохранять данные локально для того, чтобы потом оно работало в режиме оффлайн.

Приложение будет обрабатывать данные такой структуры. А для простоты я выберу всего лишь некоторые параметры. У класса GithubUser есть room-аннотация и у данных в локальной БД будет такая же структура, как и у данных в API.

У пространства DAO есть только два метода. Один — добавление информации в БД. Второй — ее извлечение.

Пространство базы данных выглядит так:

Во второй части мы реализуем Webservice, который отвечает за получение данных онлайн. Для того будем пользоваться retrofit+coroutines.

Если вы хотите узнать, как пользоваться Retrofit вместе с сопрограммами, загляните сюда .

В третьей части мы реализуем репозиторий. Этот класс будет отвечать за определение источника данных. Для нашего случая их два, так что репозиторий будет только получать данные онлайн, чтобы потом сохранить их в локальной базе данных.

Как сами видите, у репозитория есть конструктор с двумя параметрами. Первый — это класс, который представляет онлайн-данные, а второй — представляет данные оффлайн.

View-Model

После того, как мы описали модель и все ее части, пора ее реализовать. Для этого возьмем класс, родителем которого является класс ViewModel Android Jetpack.

Класс ViewModel создан для того, чтобы хранить и управлять данными, связанными с UI относительно жизненного цикла. Он позволяет данным пережить изменения конфигурации, например, повороты экрана.

View-model берет репозиторий в качестве параметра. Этот класс “знает” все источники данных для нашего приложения. В начальном блоке view-model мы обновляем данные БД. Это делается вызовом метода обновления репозитория. А еще у view-model есть свойство data. Оно получает данные локально напрямую. Это гарантия, что у пользователя всегда будет что-то в интерфейсе, даже если устройство не в сети.

Подсказка: я пользовался вспомогательным классом, который помогал мне управлять состоянием загрузки

Представление

Это последний компонент архитектуры. Он напрямую общается с представлением-моделью, получает данные и, например, передает их в recycler-view. В нашем случае представление — это простая активность.

В представлении происходит отслеживание того, как изменяются данные, как они автоматически обновляются на уровне интерфейса. Для нашего случая в представлении также отслеживается состояние операций загрузки в фоновом режиме. В процесс включено свойство loadingState, которое мы определили выше.

Вот вы и увидели, как я получил экземпляр view-model, используя для этого внедрение. А как это сработает, мы увидим дальше.

Конкретизация объектов и внедрение зависимостей

Наблюдательные заметят, что пока я еще не создал репозиторий и его параметры. Мы будет это делать точно при помощи внедрения зависимостей. А для этого в свою очередь мы берем библиотеку, Koin подходит идеально.

Так мы создадим важные объекты. Нашему приложению они нужны там же и нам останется только вызвать их в разные точки программы. Для этого и нужна магия библиотеки Koin.

В Module.kt есть объявление объекта, который нужен приложению. А в представлении мы берем inject, который говорит Koin, что нужен объект view-model. Библиотека в свою очередь старается найти этот объект в модуле, который мы определили ранее. Когда найдёт, назначит ему свойство userViewModel. А если не найдёт, то выдаст исключение. В нашем случае, код скомпилируется правильно, у нас есть экземпляр view-model в модуле с соответствующим параметром.

Похожий сценарий применится к репозиторию внутри view-model. Экземпляр будет получен из модуля Koin, потому что мы уже создали репозиторий с нужным параметром внутри модуля Koin.

Заключение

Самая сложная работа инженера ПО — это не разработка, а поддержка. Чем больше кода имеет под собой хорошую архитектуру, тем проще поддерживать и тестировать приложение. Вот почему важно пользоваться паттернами. С ними проще создать стабильно работающие программы, а не бомбу.

Вы можете найти полный код приложения у меня на GitHub по этой ссылке.

Источник

5 января 2017 г. Реализовываем MVVM в Android

Пришло время научиться делать гибкую архитектуру для Android, используя DataBinding!

Привет всем! Прежде всего хотелось бы извиниться за 9 месяцев затишья с момента публикации статьи о DataBinding. Все никак не хватало времени написать обещанное продолжение. Но в этом есть и плюсы — за это время мы успели “обкатать” некоторые решения и сделать их еще лучше 😉

Что такое MVVM?

Для начала давайте рассмотрим классическое описание этого шаблона и разберем каждый из его компонентов. Итак, Model-View-ViewModel (т.е. MVVM) — это шаблон архитектуры клиентских приложений, который был предложен Джоном Госсманом (John Gossman) как альтернатива шаблонам MVC и MVP при использовании технологии связывания данных (Data Binding). Его концепция заключается в отделении логики представления данных от бизнес-логики путем вынесения её в отдельный класс для более четкого разграничения.

Теперь давайте разберемся, что же значит каждая из трех частей в названии:

  • Model — это логика, которая связанная с данными приложения.
  • Другими словами — это POJO, классы работы с API, базой данных и пр.
  • View — собственно, это и есть layout экрана, в котором располагаются все необходимые виджеты для отображения информации.
  • ViewModel — объект, в котором описывается логика поведения View в зависимости от результата работы Model. Можно назвать его моделью поведения View. Это может быть как форматирование текста, так и логика управления видимостью компонентов или отображения состояний, таких как загрузка, ошибка, пустые экраны и т.д. Также в ней описывается поведение, которое было инициировано пользователем (ввод текста, нажатие на кнопку, свайп и т.п.)
Читайте также:  Слим джет для андроид

Что же это дает нам в конечном итоге?

  • Гибкость разработки. Этот подход повышает удобство работы в команде, т.к. пока один член команды работает над компоновкой и стилизацией экрана — другой, в это время, описывает логику получения данных и их обработки;
  • Тестирование. Такая структура упрощает написание тестов и процесс создания mock-объектов. Также, в большинстве случаев отпадает потребность в автоматизированном UI-тестировании, т.к. можно обернуть unit-тестами сам ViewModel;
  • Разграничение логики. За счет большего разграничения код становится более гибким и простым в поддержке, не говоря о его читабельности. Каждый модуль отвечает за свою конкретную функцию и только.

Так как ничего идеального не бывает, есть и недостатки:

  • Для небольших проектов этот подход может быть неоправданным.
  • Если логика привязки данных слишком сложная — отлаживать приложение будет немного труднее.

И все же — кто есть кто?

Изначально, в Android этот паттерн нуждается в небольшой модификации. Точнее сказать, нужно пересмотреть сами компоненты и их привычное восприятие.

Рассмотрим, к примеру, Activity. У нее есть layout-файл (XML) и связанный с ней Java-класс, в котором мы описываем все, что касается её работы. Получается, что xml-файл — это View, а java-класс, соответственно, ViewModel? Похоже на то, но как бы не так. А что, если я скажу, что наш класс — это тоже View? Ведь у custom view тоже есть xml и класс-обработчик, но он считается одним целым? Более того, как в активности, так и в custom view и вовсе можно обойтись без xml-файла, при этом создавая все необходимые виджеты из кода. Вот так и получается, что в нашей архитектуре View == Activity (т.е. XML + Java-class).

Но что же тогда ViewModel и, самое главное, где его размещать? Как мы могли видеть в одном из разделов предыдущей статьи, это совершенно отдельный объект. И именно его мы передавали в xml-файл используя binding.setViewModel() . В нем-то и будут поля и методы, которые нужны нам для связывания моделей с View.

Model же у нас никак не отличается от традиционного её понимания. Единственное, что хотелось бы добавить от себя — не делайте обращения к базе или API прямо во ViewModel. Вместо этого для каждого VM лучше создавать Repository — тогда код будет чище и менее громоздкий.

Таким образом мы получаем следующее: класс активности «обслуживает» только ту логику, которая относится непосредственно к View, но никоим образом не касается его поведения. К таким случаям можно отнести установку Toolbar или надстройки над TabLayout и Viewpager. Немаловажно, что только из View можно обращаться к виджетам напрямую по id ( binding.myView.doSomething() ), т.к. VM не должна знать совершенно ничего о View — коммуникация между ними реализовывается только посредством Binding. Самой же логикой загрузки данных и их отображения занимается ViewModel, а алгоритм получения данных описывается, соответственно, в Model.

Наш дизайнер ушел в отпуск, поэтому схема будет с элементами новогоднего настроения 🙂

Делать — так наверняка

Давайте перейдем непосредственно к реализации. Посмотрев на схему выше можно заметить, что View передает ViewModel не только команды (действия пользователя), но и её жизненный цикл. Почему? Потому что, отчасти, это тоже своего рода действия, которые инициируются пользователем. Ведь именно из-за его действий окно меняет свои состояния. А нам, в свою очередь, необходимо на это реагировать для корректной работы приложения. Решение напрашивается само собой — необходимо делегировать нужные нам колбэки на VM.

Представим, что нужно загружать информацию каждый раз, когда пользователь возвращается на активность. Для этого нам нужно вызывать метод загрузки данных в onResume( ).
Изменим ProfileActivity:

И определим этот же метод в ProfileViewModel:

Теперь данные будут обновляться каждый раз, когда пользователь будет возвращаться на окно. К тому же, если информация еще не была получена до этого — покажется соответствующее состояние. Все очень просто 🙂

В точности делаем и с остальными нужными нам методами. Естественно, определять это каждый раз при создании VM нецелесообразно, поэтому вынесем эту логику в базовые классы. Назовем их BindingActivity и ActivityViewModel:

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

Как по мне, так нет никакой необходимости каждый раз при создании активности описывать создание биндинга и подвязку к нему VM. Эту логику также можно вынести в базовый класс, но немного изменив привычный нам метод onCreate() . Адаптируем его для получения VM при создании активности и добавим еще пару абстрактных методов для необходимых параметров:

Осталось еще сделать базовый класс для ActivityViewModel. Здесь все проще — добавим в него только экземпляр Activity. Он пригодится нам для создания интентов а также подойдет в качестве контекста:

На этом с активностями всё — у нас есть все необходимые инструменты для описания логики, за исключением одной неприятной мелочи. Такие поля как “viewModel” и “binding” в базовой активности явно типизированы, что усложнит работу с ними, вынуждая каждый раз приводить типы. Поэтому обобщим наши классы следующим образом:

Готово! В конечном итоге мы получили такой вот класс активности:

getVariable() — должен возвращать название переменной, которое указано в тэге data->variable xml-файла активности, а getLayoutId() — должен вернуть тот самый xml. При этом также стоить отметить, что ProfileViewModel должен наследовать ActivityViewModel.

В реализации подобных классов для фрагментов есть небольшие отличия, но подробно рассматривать реализацию в рамках статьи мы не будем, т.к. концепция у них всё же схожа. Готовый класс можно будет увидеть ниже.

Несколько полезных примеров

С момента нашей последней статьи о DataBinding библиотека не только потеряла статус “бета”, но и обросла некоторыми очень полезными нововведениями. Одним из таких является двустороннее связывание (two-way binding). Это когда не только данные влияют на UI, но и наоборот. К примеру, когда пользователь вводит свое имя в EditText, значение сразу обновляется и в переменной. Ранее мы уже делали подобную фичу, однако для этого привлекались TextWatcher и BindingAdapter. Теперь же достичь этого можно намного проще (я бы даже сказал проще некуда). Все, что для этого нужно — изменить
android:text=»@« на android:text=»@=« (внимание на знак равенства после “@”). И всего-то 🙂 Но такие трюки работают только с полями семейства Observable (ObservableInt, ObservableBoolean, ObservableField и т.п.). Вот как теперь выглядит диалог, в котором мы меняем статус Марка:

Мы добавили здесь ViewModel для view в диалоге, т.к. передача ObservableField напрямую в variable не работает корректно (не знаю, баг это или фича, но то, что это не очевидно — факт). Точно также можно привязываться и к другим атрибутам, таким как checked у CheckBox и RadioButton, enabled и пр.

Если вам нужно как-то реагировать или менять данные во время их ввода/вывода — вы можете переопределить методы get() и/или set() у Observable-поля и там производить нужные манипуляции.

А если задача стоит только в отслеживании изменений — можно добавить OnPropertyChangedCallback:

Еще одна фича — это возможность использовать сеттеры как атрибуты в разметке. Допустим, у нас есть метод setAdapter() у того же RecyclerView. Для того, чтобы установить его, нам нужно обращаться непосредственно к экземпляру виджета и вызывать его метод прямо из кода, что противоречит нашему подходу. Для решения этой проблемы можно создавать BidningAdapter, или вообще CustomView, который будет расширять RecyclerView и в нем добавлять свои атрибуты. Но, согласитесь, это не лучший вариант.
К счастью, все намного проще — благодаря кодогенерации мы можем указывать в xml название сеттера при этом просто опуская “set”. Таким образом, задать адаптер можно вот так:

Префикс “bind” — этот все тот же “appliaction namespace”, и, если он уже объявлен, их лучше попросту дублировать для того, чтобы не путать объявленные кастомные атрибуты с атрибутами, сгенерированными с помощью биндинга:

Тем не менее, идея с CustomView имеет право на жизнь в случае, если нужного сеттера в виджете нет (или он назван по неподходящему нам формату).

Возможно кто-то из вас уже задался вопросом о том, как в при такой архитектуре передавать параметры во ViewModel? Здесь все также применяется подход с делегированием, но для удобства мы создаем статический метод open (или openForResult) в котором перечисляем все необходимые параметры. Дальше достаем их и передаем во ViewModel, в котором есть соответствующий конструктор. Например, передадим нашей активности статус как параметр:

Еще одна небольшая наработка, которой хотелось бы поделиться — это вынесение полей “isLoading” и “isError” в базовый класс ViewModel. Эти поля публичные и относятся к типу ObservabeBoolean — благодаря этому нет необходимости дублировать логику состояний загрузки и ошибки, а реагировать на их изменение можно простым include:

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

Забудем о boilerplate!

За время использования MVVM в разработке мы столкнулись с тем, что нам приходилось писать много надоедливого кода: модификация Activtiy/Fragment под базовые классы, прописывание длинных названий Binding-классов в дженериках, создание и связывание ViewModel, а на ранних стадиях и вовсе приходилось копировать базовые классы из проекта в проект, что также занимало драгоценное время. Именно поэтому мы создали библиотеку и плагин для Android Studio, с помощью которых эта рутина стала занимать всего 2-3 клика.

Библиотека AndroidMvvmHelper — это набор базовых классов для удобной работы с MVVM. В этот перечень входят классы как для работы с Activity (BindingActivity и ActivityViewModel), так и с Fragment (BindingFragment и FragmentViewModel), в которых уже реализована логика связывания, а также определены необходимые методы для получения callback-ов. Для того, чтобы начать ее использовать — необходимо просто определить зависимость в grdale-файле:

Хотя решение с библиотекой и упрощает жизнь, создание классов все еще достаточно трудоемкий процесс. Для решения этой задачи мы разработали плагин для IntelliJ IDEA и Android Studio — MVVM Generator. Он позволяет в один клик создать класс BindingActivity (или BindingFragment), его ViewModel, подготовленный xml-файл для разметки и зарегистрировать компонент в AndroidManifest (в случае активности, конечно же). Кроме того, если плагин не обнаружит зависимости библиотеки MVVMHelper, она будет автоматически добавлена.

Чтобы его установить, нужно зайти в раздел управления плагинами:

В нем нажать кнопку “Browse repositories” для поиска доступных плагинов в сети:

В поле поиска вводим “MVVM Generator”, выбираем найденный плагин и жмем “Install”:

По окончанию установки необходимо перезапустить IDE. После этого плагин готов к работе.

Теперь давайте создадим фрагмент профиля. В случае, как и при создании обычного класса, вызываем контекстное меню на нужном пакете и выбираем “Create Binding Fragment”

После того, как мы введем название фрагмента (в нашем случае это “ProfileFragment”) мы получим следующее:

Заглянув внутрь, мы увидим готовые к работе классы:

Помимо этого у нас сразу готов xml:

И все это буквально за пару секунд! Итак.

Резюмируя

На сегодняшний день плагин очень простой и решает только главную задачу — генерацию файлов. В планах присутствуют добавление проверки на наличие биндинга, более гибкая валидация названий, конфигурация расширенных шаблонов активностей и фрагментов и много другое, но пока — имеем то, что имеем.

С момента выхода стабильной версии DataBinding наша команда уже успела реализовать несколько проектов с помощью этого подхода. Из собственного опыта могу лишь сказать, что мне не хочется возвращаться к более традиционным способам написания приложений, а когда все же приходится это делать — чувствуешь себя человеком из будущего. В целом рутинной работы стало меньше, а потому и процесс разработки стал интересней. К тому же, ребята из Google активно работают над адекватной поддержкой этой технологии в Android Studio, что значительно минимизирует неудобства при разработке. Теперь же — это основной подход, который используется нами при создании приложений.

Надеемся, что наш опыт поможет упростить жизнь при создании MVVM-архитектуры в Ваших приложениях так же, как это помогает нам 🙂

Источник

Читайте также:  Как нарисовать андроид карандашом
Оцените статью