В моем предыдущем блоге об использовании Room с Android я описал, как можно использовать Room для эффективного хранения данных приложения после того, как пользователь вышел из вашего приложения, для лучшего взаимодействия с пользователем. Если вы не читали этот блог, вы можете прочитать его здесь:



Но как насчет случаев, когда ваше приложение работает и его состояние изменяется - например, когда ориентация телефона изменяется с книжной на альбомную и наоборот?

Обычно, когда вы это делаете, приложение перезапускается, тем самым теряя текущее состояние и запускаясь заново. Хотя этот поток вполне разумен (поскольку ваше приложение может иметь разные ресурсы для ландшафтного и портретного режима), базовые данные, которые оно использует, одинаковы.

Например, в моем приложении AfterShoot я получаю и отображаю список изображений, хранящихся в базе данных SQL, с устройства пользователя. Этот список изображений извлекается при первом запуске приложения, и его не нужно повторно извлекать из базы данных, поскольку база данных не будет обновляться.

Когда я поворачиваю приложение, этот список очищается, и изображения снова выбираются из базы данных; что не имеет смысла, потому что мы уже извлекали изображения из базы данных при первом запуске.

Чтобы решить эту проблему, вам может быть предложено использовать удобный метод onSaveInstanceState(), и хотя он может работать для большинства сценариев, проблема с этим методом заключается в том, что Bundle может сохранить не более 1 МБ данных. В моем случае список изображений, которые у меня были, был опасно близок к этому пределу (около 835 кб).

Использование ViewModels также удобно при создании приложения, которое извлекает и отображает данные из API (например, новостное приложение). Без ViewModels вам придется получать данные из API каждый раз при повороте телефона. Подумайте о сценарии, когда вы читаете последние новости, но как только вы переводите телефон в альбомный режим, ваше приложение предлагает вам повторно загрузить эти новости! Это было бы невероятно неприятно - такой тип пользовательского интерфейса может сделать или сломать ваше приложение.

В этом сообщении блога мы рассмотрим ViewModels и то, как они могут помочь нам в решении этой проблемы.

О ViewModels

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

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

Что касается жизненного цикла ViewModel, то вот как это выглядит:

Как видите, область ViewModel остается активной на протяжении всего жизненного цикла Activity / Fragment вашего приложения и уничтожается только тогда, когда Activity / Fragment уничтожается. Это также гарантирует, что ViewModel не будет разрушен, если Activity / Fragment будет уничтожен, а затем воссоздан из-за изменения ориентации.

Это официально ... мы живем в будущем. Мобильные приложения могут видеть, слышать, чувствовать и думать в режиме реального времени. И у Fritz AI есть инструменты и опыт, чтобы сделать все это возможным.

Использование ViewModels в Android

Что касается AfterShoot, мой текущий код выглядит так:

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

Теперь мы заменим это ViewModels. Давайте посмотрим на необходимые шаги.

Шаг 1. Добавление зависимости ViewModel

Перед использованием ViewModel вам необходимо добавить следующую зависимость в build.gradle файл вашего приложения:

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

Шаг 2. Определите класс ViewModel, содержащий ваши переменные

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

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

Внутри этого класса мы теперь извлекаем и сохраняем все наши списки, которые мы извлекли и сохранили в классе Fragment ранее.

Шаг 3. Инициализируйте переменные в ViewModel.

Теперь, когда мы создали ViewModel, следующим шагом будет инициализация всех переменных, которые будут здесь храниться. Вот как это выглядит для меня:

Чтобы получить доступ к вашему контексту, вы можете использовать удобный параметр application, переданный в класс ImageViewModel.

Ищете искру, чтобы вывести свои приложения на новый уровень? Машинное обучение обеспечивает мощный и персонализированный мобильный опыт. Подпишитесь на рассылку Fritz AI Newsletter, чтобы узнать, как это сделать.

Шаг 4. Доступ к данным из ViewModel

Чтобы получить доступ к данным из фрагмента или действия, мы не будем сами создавать экземпляр этого класса. Вместо этого мы сообщим классу ViewModelProviders, к какому ViewModel мы хотим получить доступ, а затем он позаботится либо о создании для нас нового экземпляра, либо о возврате существующего. Вот как это выглядит:

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

LifeCycleOwner вот класс, который будет управлять LifeCycle нашего ViewModel. Если вы установите LifeCycleOwner в качестве текущего Activity, ViewModel будет жить, пока живет Activity. И если вы установите его как текущий Fragment, то ViewModel будет жить, пока жив ваш Fragment.

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

Предупреждение с ViewModels

При использовании ViewModel важно помнить, что вы не сохраняете какие-либо специфические для Android компоненты в вашей ViewModel. Например, использование ViewModel для хранения Activity или View не является хорошей практикой, так как это может привести к утечке памяти, поскольку Activity или View, ссылка на которые хранится в ViewModel, не будет собираться мусором, пока ViewModel находится в в живых.

В идеале ViewModels следует использовать только для хранения данных, не связанных с Android, которые необходимо получить один раз в течение жизненного цикла Activity.

Если вы хотите взглянуть на мою реализацию ViewModels в AfterShoot, вы можете найти исходный код для нее в моем репозитории GitHub:



Спасибо за внимание! Если вам понравилась эта история, пожалуйста, нажмите 👏 кнопку и поделитесь ею, чтобы помочь другим найти ее! Не стесняйтесь оставлять комментарии 💬 ниже.

Есть отзывы? Подключим в Twitter.

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

Являясь независимой редакцией, Heartbeat спонсируется и публикуется Fritz AI, платформой машинного обучения, которая помогает разработчикам учить устройства видеть, слышать, ощущать и думать. Мы платим участникам и не продаем рекламу.

Если вы хотите внести свой вклад, переходите к нашему призыву участников. Вы также можете подписаться на наши еженедельные информационные бюллетени (Deep Learning Weekly и » «Информационный бюллетень Fritz AI), присоединяйтесь к нам на » « Slack и следите за Fritz AI в Twitter , чтобы узнавать обо всех последних новостях в области машинного обучения для мобильных устройств.