Найти в Дзене
Hiplabs

Offline-first Android приложения

В наше время большинство разрабатываемых мобильных приложений являются клиентами к каким-либо сервисам: интернет-магазин, социальная сеть, новостной сайт и тому подобное. Разработка таких приложений зачастую состоит из разработки следующего функционала: Большая часть работы сводится к однотипным экранам и их вариациям в различных приложениях. Неотъемлемой частью таких приложений является работа с сервером: получение, отправка, редактирование данных и так далее. Естественно, осуществление таких операций требует наличия интернет-соединения. И вот, в один момент у нас появляется проект, одним из требований к которому является работоспособность при отсутствии интернета. О том, как это было реализовано, и с чем нам пришлось столкнуться, и будет эта статья. О Проекте Приложение является клиентом к разрабатываемой нами платформе Doma.ai — нацеленной на автоматизацию, оптимизацию и облегчение ведения бизнеса в сфере жилищно-коммунальных услуг. Пользователи этого приложения — сотрудники ЖКХ
Оглавление

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

  • Логин/Регистрация;
  • Просмотр списка (новости, посты, товары);
  • Просмотр деталей (новость, пост, товар);
  • Просмотр/Редактирование профиля.

Большая часть работы сводится к однотипным экранам и их вариациям в различных приложениях. Неотъемлемой частью таких приложений является работа с сервером: получение, отправка, редактирование данных и так далее. Естественно, осуществление таких операций требует наличия интернет-соединения.

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

О Проекте

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

Задача приложения

Основной задачей приложения является реализация потока выполнения заявок:

  • Создание;
  • Редактирование;
  • Выполнение (последовательное изменение статуса в процессе работы над заявкой);
  • Комментирование;
  • Прикладывание документов.

Почему offline-first?

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

Собственно, из-за этих двух факторов единственным подходящим решением является offline-first работа приложения.

Какие проблемы нас ждали?

Первое, с чем пришлось столкнуться — как реализовать периодическую отправку данных?

Первой идеей было создание foreground-сервиса, который бы раз в N-минут делал отправку и получение данных. Такой подход решал задачу, но приводил к серьезным затратам батарейки (устройства в таком режиме использования садились за считанные часы)

В итоге выбор пал на JobScheduler и JobService — в JobService производится синхронизация, а JobScheduler позволяет запланировать выполнение раз в 15 минут. Данная связка использовалась для синхронизации в те моменты, когда приложение свернуто. Для синхронизации в процессе работы с приложением (на переднем плане) используется Observable.interval, который раз в 5 минут запускал выполнение JobService. Переключение между тем или иным способом синхронизации происходило в ApplicationActivity, приложение построено по принципу SingleActivity, а, следовательно, уход ApplicationActivity в фон — означает уход всего приложения в фон.

Второе — реализация бизнес-логики сервера на клиенте. Что это значит?

Так как данные изменяются локально, а лишь затем, спустя время отправляются на сервер, необходимо быть уверенными в том, что такое изменения возможно, поэтому многие вещи пришлось дублировать в мобильном приложении. К примеру, «Может ли этот пользователь писать сообщения в чат с жителями?», «На какой статус возможен переход из текущего?», «Можно ли показывать текущему пользователю номер телефона жителя?» и тому подобное. Какой-то серебряной пули для решения этой проблемы нет, что-то получилось частично вынести на сервер — дерево переходов по статусам подгружается при синхронизации с сервера, что-то решается локально — по роли пользователя определяется, может ли он писать/звонить жителям. Также из-за того, что бизнес-логика дублируется на клиенте, приходится заметно чаще выпускать обновления, так как если вдруг в процессе работы с заявкой появились какие-то логические изменения — их также необходимо добавить и в приложение.

Третье — гарантия целостности данных.

Так как мобильное приложение позволяет провести в офлайне весь жизненный цикл заявки — от создания до выполнения, пришлось ввести приоритетность отправки данных:

  • Запросы создания заявки;
  • Запросы изменения заявки;
  • Запросы загрузки файлов на сервер;
  • Запросы создания документов и комментариев;
  • Запросы изменения статуса.

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

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

Заключение

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

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

Если у вас еще есть вопросы или необходимо разработать мобильное приложение, более подробную информацию ищите на нашем сайте https://hiplabs.dev или пишите нам на info@hiplabs.dev. Мы поможем решить вашу задачу.