- Что такое режим офлайн? Включение, отключение, работа на разных устройствах и приложениях
- Для чего нужен офлайн-режим на компьютерах?
- Автономный режим в мобильном телефоне
- Убираем офлайн-режим в браузерах
- Офлайн как синоним невидимости
- Работа с некоторыми интернет-приложениями офлайн
- Выход из офлайн-режима
- В заключение
- Оффлайн-режим на iOS и особенности его реализации на Realm
- Offline-first-подход
- Работа с идентификаторами объектов
- Хранение несинхронизированных изменений
- Синхронизация с сервером
- Дополнительные workaround при работе с Realm
Что такое режим офлайн? Включение, отключение, работа на разных устройствах и приложениях
Что такое режим офлайн? Если говорить простым языком, это возможность работы в каком-либо приложении при отсутствии доступа к связи. Для компьютеров это отключение, прежде всего, Интернета, возможно, и локальной сети. Для мобильных телефонов это также отключение и телефонной связи, и Bluetooth.
Для чего нужен офлайн-режим на компьютерах?
Большинство пользователей ПК, даже работая в программах, которые не связаны с необходимостью доступа в Интернет, постоянно к нему подключены. Некоторые — по привычке, другие — из-за использования таких операционных систем, как ChromeOS. В данной системе все действия совершаются через Интернет. Если вам понадобится что-либо распечатать, а доступа к Сети нет, то вы ничего не сможете сделать, если, конечно, документ не сохранен в локальном хранилище и нет другой операционной системы.
Помимо этого, известно, что Google отслеживает действия пользователей и передает их личные данные американским спецслужбам по требованию. Если вы не озабочены проблемами конфиденциальности, то вспомните о том, что для MS Windows, которой пользуется большинство пользователей, в Сети полно вирусов, и подцепить их там, где Интернет можно было не использовать, порой достаточно обидно.
Автономный режим в мобильном телефоне
После того как мы разобрались, что такое режим офлайн в компьютере, посмотрим, что он собой представляет в мобильном телефоне.
В телефонах, в которых установлена операционная система Android, он называется «Автономным режимом». Его используют в тех местах, где использование мобильной связи недопустимо. Примером такого места может являться самолет, поэтому часто этот режим в телефонах называют «Режимом полета». Использование данного режима позволяет экономить батарею, которая, как известно, имеет свойство разряжаться в самое неподходящее время.
Как отключить офлайн-режим? В разных телефонах это происходит по-разному. Обычно данная опция находится в «Настройках», где нужно выбрать «Профили» или «Режимы», а там уже поставить галочку напротив «Обычный режим». В некоторых моделях требуется перезагрузка, после чего будет автоматически предложено перейти в обычный режим.
Убираем офлайн-режим в браузерах
В случае если у вас лимитированный трафик, который неожиданно стал заканчиваться, нужно срочно выходить в режим офлайн. Что такое в этом случае предпринимается? Следует включить в браузерах, с помощью которых осуществлялся выход во Всемирную сеть, автономный режим. Тогда многие страницы из тех, которые посещались во время работы Интернета, можно будет просмотреть из кэша.
В этом случае ответ на вопрос «как убрать офлайн-режим» достаточно тривиален — нужно снять галочку с «Автономного режима». В новых версиях браузеров обычно панель меню скрыта, поэтому ее нужно вызвать доступным способом, например, нажав Alt на клавиатуре, а там уже выбрать «Автономный режим».
Офлайн как синоним невидимости
Термин «офлайн» стал настолько популярным, что его стали использовать не только как показатель отсутствия Сети, но и как показатель реального или мнимого отсутствия в Сети. Так, можно зайти в социальную сеть «ВКонтакте» и сделаться невидимым для других пользователей. То есть вы будете присутствовать на сайте, но для других пользователей ваш статус указывает совсем противоположную информацию. Это также называют «нахождением в офлайне».
Работа с некоторыми интернет-приложениями офлайн
Изначально онлайновые приложения, такие как «Гугл документы», получили возможность работать в офлайн-режиме. Можно отметить, что это способствует здоровому соперничеству между создателями офисных приложений, прежде всего корпорациями Microsoft и Google, что должно повысить их конкурентоспособность.
Как включить офлайн-режим в «Гугл документах»? Этого возможно добиться, используя браузер Chrome или его открытый аналог Chromium. Открываем в нем свое «облако» в «Гугле» (Google Drive) — для этого нужен интернет, далее в панели навигации щелкаем по кнопке «Еще». Выбираем категорию «Автономные», в результате чего появится инструкция, в которой указано, что сначала нужно установить аддон для этих целей, после чего нажать кнопку доступа офлайн. Это приведет к тому, что файлы из «облака» будут скопированы на локальное устройство хранения. После этого можно отключать интернет и работать с «Гугл Документами» офлайн.
Таким образом, мы ответили на вопрос: «Как включить офлайн-режим в приложениях «Гугл Докс»?»
Подобным образом можно работать и с «Гугл картами». При нахождении в онлайн-режиме указывается область на карте, которая будет необходима при работе офлайн. Затем карта скачивается, и по данной области можно будет осуществлять поиск офлайн.
В мобильном телефоне офлайн-режим может быть включен не только полным отключением мобильной сети, но и отключением одного интернета с помощью снятия галочки с «Использования мобильных данных».
Выход из офлайн-режима
Иногда для отдельных приложений выход из офлайна может блокироваться файерволами. Так, в «Стиме» для игр также предусматривается режим офлайн. При этом в Social Club некоторые пользователи не могут покинуть офлайн-режим. Для того чтобы снять это ограничение, необходимо зайти в настройки файервола и откорректировать там правила и зоны. Здесь этим файлам Social Club дано табу на выход в Интернет. Его необходимо снять, после чего выход из офлайн-режима станет возможным.
Это относится не только к Social Club, но и к некоторым играм Steam. Возможно, наблюдается и в других приложениях.
Как выйти из офлайн-режима? Если данная операция заблокирована, идем в файервол, проверяем правила и зоны, делаем их разрешительными для данного приложения. Если такое встречается часто, проверьте настройки брандмауэра Windows.
В заключение
Подведем итог: что такое режим офлайн? Помимо того, что это режим без доступа к Интернету, под данным термином понимают и невидимость в некоторых социальных сетях. Некоторые интернет-приложения способны работать офлайн, при этом скачивая «облачные» файлы на локальные хранилища.
Источник
Оффлайн-режим на iOS и особенности его реализации на Realm
Автор: Екатерина Семашко, Strong Junior iOS Developer, DataArt
Немного о проекте: мобильное приложение для платформы iOS, написанное на языке Swift. Цель приложения — возможность шаринга дисконтных карт между сотрудниками компании и их друзьями.
Одной из целей проекта было изучить и попробовать на практике популярные технологии и библиотеки. Для хранения локальных данных выбрали Realm, для работы с сервером — Alamofire, для аутентификации использовался Google Sign-In, для загрузки изображений — PINRemoteImage.
Основные функции приложения:
- добавление карты, ее редактирование и удаление;
- просмотр чужих карт;
- поиск карт по названию магазина/имени пользователя;
- добавление карт в список избранных для быстрого доступа к ним.
Возможность использовать приложением без подключения к сети предполагалась с самого начала, но только в режиме чтения. Т.е. мы могли просматривать информацию о картах, но не могли модифицировать их без интернета. Для этого в приложении всегда была копия всех карт и брендов базы с сервера, плюс список избранных для текущего пользователя. Поиск тоже реализовывался локально.
Позже мы решили расширить оффлайн, добавив режим записи. Информация об изменениях, сделанных пользователем, сохранялась и при появлении интернет-соединения синхронизировалась. О реализации такого read-write оффлайн-режима и пойдет речь.
Что необходимо для полноценного оффлайн-режима в мобильном приложении? Нам нужно убрать зависимость пользователя от качества интернет-соединения, в частности:
- Убрать зависимость ответов пользователю на его действия в UI от сервера. В первую очередь запрос будет взаимодействовать с локальным хранилищем, потом уже будет отправляться на сервер.
- Помечать и хранить локальные изменения.
- Реализовать механизм синхронизации — при появлении интернет-соединения нужно отправлять изменения на сервер.
- Отображать пользователю какие изменения синхронизированы, какие нет.
Offline-first-подход
Первым делом мне пришлось изменить существующий механизм взаимодействия с сервером и базой данных. Цель была в том, чтобы пользователь не чувствовал зависимости от наличия или отсутствия интернета. В первую очередь он должен взаимодействовать с локальным хранилищем данных, а запросы на сервер должны идти в фоновом режиме.
В предыдущей версии присутствовала сильная связь между слоем хранения данных и сетевым слоем. Механизм работы с данными был следующим: сначала шел запрос на сервер через класс NetworkManager, мы ждали результата, после этого данные сохранялись в базу через класс Repository. Потом результат отдавался на UI, как представлено на схеме.
Для реализации offline-first-подхода я разделила слой хранения данных и сетевой слой, введя новый класс Flow, который управлял порядком вызова NetworkManager и Repository. Теперь данные сначала сохраняются в базу через класс Repository, потом результат отдается на UI, и пользователь продолжает работу с приложением. В фоновом режиме идет запрос на сервер, после ответа обновляются информация в базе данных и UI.
Работа с идентификаторами объектов
При новой архитектуре появилось несколько новых задач, одна из которых — работа с id объектов. Раньше мы получали их от сервера при создании объекта. Но теперь объект создавался локально, соответственно, необходимо было генерировать id и после синхронизации обновлять их на актуальные. Тут я столкнулась с первым ограничением Realm: после создания объекта менять его первичный ключ нельзя.
Первым вариантом было отказаться от первичного ключа в объекте, сделать id обычным полем. Но при этом терялись преимущества использования первичного ключа: индексирование Realm, что ускоряет fetch объекта, возможность обновления объекта с флагом create (создать объект, если его не существует), соблюдение требования уникальности объекта.
Я хотела сохранить первичный ключ, но он не мог быть id объекта с сервера. В результате рабочим решением было иметь два идентификатора, один из них серверный, optional поле, а второй — локальный, который и был бы первичным ключом.
В итоге локальный id генерируется на клиенте при создании объекта локально, а в случае, когда объект приходил с сервера, он равен серверному id. Т. к. в приложении single source of truth является база данных, при получении данных с сервера объекту проставляется актуальный локальный идентификатор, и работа идет только с ним. При отправке данных на сервер передается серверный идентификатор.
Хранение несинхронизированных изменений
Изменения объектов, которые еще не были отправлены на сервер, необходимо хранить локально. Это можно реализовать следующими способами:
- добавлением полей к существующим объектам;
- хранением несинхронизированных объектов в отдельных таблицах;
- хранением отдельных изменений полей в каком-то формате.
Я не использую объекты Realm напрямую в своих классах, а делаю их маппинг на свои, чтобы избежать проблем с многопоточностью. Автообновление интерфейса идет с помощью auto-updating results выборок, где я подписываюсь на обновления запросов. Только первый подход работал с моей текущей архитектурой, поэтому выбор пал на добавление полей к существующим объектам.
Больше всего изменений претерпел объект карты:
- synced — есть ли данные на сервере;
- deleted — true, если карта удалена только локально, необходима синхронизация.
Идентификаторы, о которых шла речь в предыдущей части:
- localId — первичный ключ сущности в приложении, либо равный серверному id, либо сгенерированный локально;
- serverId — id с сервера.
Отдельно стоит упомянуть хранение изображений. В сущности Attachment к полю serverURL изображения на сервере добавилось поле diskURL, хранящее адрес локального несинхронизированного изображения. При синхронизации изображения локальное удалялось, чтобы не засорять память устройства.
Синхронизация с сервером
Для синхронизации с сервером была добавлена работа с Reachability, чтобы при появлении интернета запускался механизм синхронизации.
Сначала проверяется, есть ли в базе данных изменения, которые нужно отправить. Потом на сервер идет запрос о получении актуального слепка данных, в результате на клиенте отсеиваются изменения, которые не нужно посылать (например изменение объекта, который на сервере уже удалили). Оставшиеся изменения формируют очередь запросов на сервер.
Для отправки изменений можно было реализовать bulk updates, посылая изменения массивом, или же сделать большой запрос на синхронизацию всех данных. Но к тому времени бэкенд-разработчик уже был занят в другом проекте, и помогал нам только в свободное время, поэтому для каждого типа изменения создается свой запрос.
Я реализовала очередь через OperationQueue и обернула каждый запрос в асинхронную Operation. Некоторые операции зависят друг от друга, например, мы не можем загрузить изображение карты до создания карты, поэтому я добавила dependency операции изображения на операцию карты. Также операции загрузки изображений на сервер был поставлен меньший приоритет, чем всем остальным, и добавляла в очередь я их тоже последними из-за их тяжеловесности.
При планировании оффлайн-режима большим вопросом было разрешение конфликтов с сервером при синхронизации. Но когда мы дошли до этого в ходе реализации, поняли, что случай, когда пользователь меняет одни и те же свои данные на разных устройствах, очень редкий. Значит нам достаточно реализовать механизм last writer wins. При синхронизации приоритет всегда отдается неотправленным изменениям на клиенте, они не перетираются.
Обработка ошибок пока в зачаточном состоянии, при неудачной синхронизации объект будет добавлен в очередь изменений при следующем появлении интернета. И потом если он так и будет висеть несинхронизированным после мерджа, пользователь сам решит, оставить его или удалить.
Дополнительные workaround при работе с Realm
При работе с Realm столкнулись еще с несколькими проблемами. Возможно, этот опыт также будет кому-то полезен.
При сортировке по строке порядок идет согласно порядку символов в UTF-8, поддержки регистронезависимого поиска нет. Мы столкнулись с ситуацией, когда названия в нижнем регистре идут после названий в верхнем регистре, например: Магнит, Пятерочка, Лента. Если список очень большой, все названия в нижнем регистре будут внизу, что очень неприятно.
Для сохранения порядка сортировки независимо от регистра пришлось вводить новое поле lowercasedName, обновлять его при обновлении name и сортировать по нему.
Также новое поле добавили для сортировки по наличию карты в избранном, так как по сути для этого нужен подзапрос по связям объекта.
При поиске в Realm есть метод CONTAINS[c] %@ для регистронезависимого поиска. Но, увы, он работает только с латиницей. Для русских брендов тоже пришлось создавать отдельные поля и вести поиск по ним. Но позже это оказалось нам на руку для исключения специальных символов при поиске.
Как видите, для мобильных приложений вполне можно реализовать оффлайн-режим с сохранением изменений и синхронизацией малой кровью, а иногда даже с минимальными изменениями на бэкенде.
Несмотря на некоторые сложности, вы можете использовать для его реализации Realm, получая при этом все преимущества в виде live updates, zero-copy architecture и удобного API.
Так что нет никакой причины лишать ваших пользователей возможности доступа к данным в любой момент, вне зависимости от качества соединения.
Источник