Офлайн-режим мобильного приложения: данные, синхронизация и конфликты
Офлайн-режим приложения: локальные данные, очередь изменений, повторы, конфликты и файлы. Как сохранить работу пользователя и проверить синхронизацию.
Офлайн-режим приложения нужен, когда полезное действие не должно полностью зависеть от связи: сотрудник собирает данные на объекте, покупатель читает сохранённый каталог, специалист заполняет отчёт в дороге. Но отсутствие сети не делает серверные правила необязательными. Приложение должно различать локально сохранённое действие и подтверждённый результат, а после восстановления связи — управляемо синхронизировать данные. Ниже разберём постановку задачи, локальное хранение, очередь изменений, конфликты и проверку офлайн-сценариев. Это материал для владельца мобильного продукта и команды разработки. Примеры условные. Не существует универсального режима, который позволяет безопасно выполнять любые операции без сервера: допустимость определяется процессом и последствиями ошибки. Что такое офлайн-режим мобильного приложения Офлайн-режим — способность приложения выполнять согласованные сценарии при отсутствии или нестабильности сети, используя локально доступные данные. Он включает понятное состояние информации, сохранение допустимых изменений и правила синхронизации. Пользователь должен знать, что сохранено на устройстве, что ожидает отправки и что уже подтверждено сервером. Разделите чтение и действие. Показ загруженного документа обычно проще, чем резерв товара или проведение оплаты. Часть операций можно подготовить локально, но подтверждение требует сервера. Для других допустим только онлайн-путь. Это должно отражаться в интерфейсе: недоступная кнопка объясняет причину и предлагает безопасный следующий шаг. Не называйте офлайн-режимом только красивую заглушку «нет интернета». Полезный сценарий сохраняет данные, контекст и результат работы. Если человек заполнил форму и потерял её при сетевой ошибке, режим не решает задачу. При этом автоматическое продолжение неизвестной операции тоже опасно: необходимо знать, что сервер успел выполнить. Какие сценарии стоит поддержать Выберите действия по условиям работы пользователя. На выезде важны сохранённые задания, справочная информация, заметки и фотографии. В каталоге — просмотр ранее загруженных позиций. В сервисе заказов — подготовка корзины, но не обещание актуальной доступности. Список определяется потребностью, а не желанием сделать «всё офлайн». Для каждого сценария укажите данные, допустимый возраст и момент подтверждения. Если инструкция меняется редко, локальная копия может быть полезна дольше. Если цена или остаток меняются быстро, нужно показать актуальность и запросить проверку перед заказом. Одно правило устаревания для всех данных обычно слишком грубо. Сценарий Что доступно без сети Что требует подтверждения Рабочее задание Сохранённый текст и допустимые отметки Актуальность назначения и итоговый статус Отчёт с объекта Черновик, заметки и вложения Приём сервером и проверка правил Каталог Загруженные карточки Текущая цена и доступность перед заказом Документ Разрешённая локальная копия Актуальная версия и право дальнейшего доступа Сразу выделите исключения. Если операция влияет на деньги, склад или права других людей, допустимость локального исполнения требует особого решения. Иногда безопасный вариант — сохранить намерение и выполнить его после проверки сервера. Пользователь должен понимать, что подготовка не равна завершению. Локальные данные как управляемый ресурс На устройстве нужен согласованный набор данных, а не бесконтрольная копия всей системы. Опишите, какие сущности загружаются, когда обновляются, как удаляются и кто имеет доступ. Состав зависит от роли и сценария. Если пользователь не должен видеть определённые сведения онлайн, они не должны попадать в локальный набор. В руководстве Android по offline-first рассматриваются локальный и сетевой источники данных, а также слой, который согласует их. Это полезная архитектурная отправная точка. Для конкретного продукта всё равно нужно отдельно определить бизнес-подтверждение операции и правила конфликтов: локальная запись не заменяет серверное решение. Хранение должно переживать предусмотренные состояния: закрытие приложения, перезапуск устройства и обновление версии. Черновик в памяти не поможет человеку, который потерял связь и случайно закрыл экран. Укажите, какие действия сохраняются сразу, а какие требуют явного подтверждения. Проверяйте реальное поведение, а не только код обработчика кнопки. Планируйте очистку. Кеш справочника и незавершённый отчёт имеют разную ценность. Удаление старых файлов не должно уничтожать данные, которые ещё не отправлены. Пользователь должен понимать объём хранения и допустимые действия при нехватке места. Молчаливое удаление важного черновика — продуктовый дефект. Актуальность и состояние информации Показывайте актуальность там, где она влияет на решение. «Загружено ранее» и «подтверждено сейчас» не должны выглядеть одинаково. Можно указать время последнего обновления, состояние связи и ограничение действия. Не перегружайте каждый экран техническими деталями, но не скрывайте существенную неопределённость. Учебный пример: сотрудник открыл сохранённое задание, которое другой диспетчер уже отменил. Без связи он может подготовить отчёт, но окончательная отправка должна учесть новое состояние. Интерфейс после синхронизации объясняет конфликт и сохраняет результат труда. Автоматическое стирание черновика не является приемлемым разрешением ситуации. Устаревание может быть разным по полям. Фото и описание товара доступны, а цена требует проверки. Документ существует, но право доступа изменилось. Чтобы не создавать ложную уверенность, моделируйте состояния отдельно. Одна глобальная зелёная надпись «синхронизировано» не объясняет, какая часть данных действительно актуальна. Не полагайтесь только на системный индикатор сети. Подключение к Wi-Fi не подтверждает доступность API или авторизации. Приложение должно корректно обрабатывать фактические ответы и тайм-ауты. Пользовательский текст описывает доступность действия, а не предполагаемое качество соединения. Очередь локальных изменений Допустимые изменения сохраняются в устойчивую очередь с идентификатором, содержимым, состоянием и связью с пользователем. Это позволяет продолжить отправку после перезапуска. Для каждой записи нужно знать, что отправляется и как подтвердить результат. Простое повторение последнего HTTP-запроса без модели операции может создать дубли. Разделяйте состояния: подготовлено, ожидает отправки, отправляется, подтверждено, требует исправления или отменено. Конкретные названия могут быть проще, но смысл должен оставаться ясным. Пользователь должен видеть, что работа сохранена и ещё не принята сервером. Оператору нужны сведения для диагностики без доступа к лишним данным. Порядок операций определяется связями. Нельзя отправить фотографию отчёта до создания нужного объекта, если контракт этого не допускает. При этом независимые изменения не обязательно блокировать одним сбойным сообщением. Опишите зависимости и правила продолжения, чтобы очередь не превращалась в вечное ожидание первой ошибки. Повтор должен использовать устойчивый ключ. Если сервер выполнил действие, а ответ потерялся, клиент проверяет подтверждение либо повторяет идемпотентную операцию по договорённому контракту. Иначе пользователь увидит один отчёт, а сервер получит два. Приёмка включает именно потерю ответа, а не только полное отсутствие сети. Конфликты после восстановления связи Конфликт возникает, когда локальное изменение опирается на состояние, которое уже изменилось на сервере. Выберите правило для конкретной сущности: принять, объединить, отклонить или предложить выбор. Универсальное «последняя запись побеждает» может потерять чужую работу и не подходит автоматически для значимых операций. Учебная ситуация: два сотрудника изменили комментарий к одному объекту. Если это независимые записи, их можно сохранить обе. Если они меняют единое поле состояния, понадобится проверка допустимого перехода. Если действие касается количества товара, простая замена числом может нарушить учёт. Правило зависит от смысла данных. Показывайте конфликт без потери введённого результата. Человек должен увидеть, что изменилось, какое действие доступно и что будет сохранено. Если нужен оператор, создайте наблюдаемое обращение. Не заставляйте пользователя угадывать, почему после восстановления связи его экран вернулся к прежнему значению. Версия объекта или другой механизм контроля должен быть частью контракта. Клиент сообщает, на каком состоянии основано изменение, сервер проверяет применимость. Способ реализации зависит от продукта, но тест должен воспроизводить параллельное изменение. Проверка только одного устройства оставляет этот риск невидимым. Фотографии и большие вложения Вложения требуют отдельной модели: локальный файл, подготовка, загрузка и связь с серверным объектом. Если отправка прервана, текст отчёта может быть принят, а фото — ещё нет. Пользователь должен видеть это различие. Не обозначайте весь отчёт завершённым до согласованного подтверждения обязательных частей. Проверяйте размер, формат и доступное место. Сжатие может уменьшить передачу, но не должно уничтожить важные детали, например маркировку оборудования. Параметры выбирают по задаче и проверяют на характерных материалах. Для чувствительных вложений нужна согласованная защита и политика локального хранения. Продолжение передачи зависит от возможностей API и выбранного механизма. Если поддерживается повтор по частям, части должны принадлежать правильному объекту и версии. Если файл отправляется целиком, повторы должны быть ограничены и наблюдаемы. Не обещайте пользователю незаметную загрузку при любых условиях устройства. Удаление локальной копии выполняйте после подтверждения по правилам продукта. Если сервер сообщил только приём запроса, но ещё не обработал файл, ранняя очистка может лишить систему возможности восстановиться. Отдельно проверяйте отмену отправки, повторный выбор файла и обновление приложения во время загрузки. Авторизация и смена пользователя Локальные данные должны принадлежать правильному пользователю и контуру. После выхода либо смены аккаунта нельзя показывать информацию предыдущего человека. Очередь изменений тоже имеет владельца. Если несколько сотрудников используют одно устройство, сценарий передачи требует особого внимания. Истечение сессии не должно молча терять черновик. Можно сохранить локальный результат и запросить вход перед отправкой, если это соответствует политике продукта. После входа нужно убедиться, что право на объект всё ещё действует. Повторная авторизация не автоматически подтверждает любой ранее подготовленный запрос. Отзыв права доступа и отсутствие сети создают ограничения, которые следует обсуждать заранее. Сервер не может мгновенно сообщить устройству без связи о каждом изменении. Поэтому состав локальных данных и допустимый срок использования определяют с учётом риска. Нельзя обещать немедленный отзыв всех офлайн-копий без соответствующего механизма. Проверяйте выход с незавершённой очередью. Пользователю нужно объяснить последствия и безопасный путь. Если продукт допускает отправку позже, она не должна перейти к чужому аккаунту. Если данные очищаются, действие должно соответствовать согласованным правилам и не скрывать потерю важной работы. Фоновая синхронизация и ограничения устройства Операционная система может ограничивать фоновые действия, поэтому продукт не должен обещать непрерывную отправку вне приложения без проверки условий платформы. Продумайте продолжение при следующем открытии и явный способ проверить состояние. Пользователь должен иметь путь завершить работу, даже если фоновая попытка не состоялась. Учитывайте питание, сеть и объём передачи. Большие вложения могут требовать отдельного выбора пользователя или согласованного режима. Повторы должны иметь управляемый интервал и остановку при ошибке данных. Частая бесконечная отправка расходует ресурсы и не решает конфликт бизнес-правила. Синхронизация должна быть наблюдаемой, но спокойной. Для обычного действия достаточно состояния и количества ожидающих элементов. Для ошибки — причина и действие. Технические детали можно оставить в диагно
Автор: Владислав Орлов, iOS Developer, 404gen.
404gen — креативное digital-агентство полного цикла, работаем удалённо по всей России.
Телефон: +7 993 729-59-59 (пн–пт, 10:00–19:00 МСК). WhatsApp: +7 913 141-20-96. Telegram: @aporkulevich. Почта: ap@404gen.ru.