Предотвратите цикл синхронизации сети при синхронизации с сетью в Android ContentProvider

Я пишу свой собственный ContentProvider, который будет синхронизироваться с веб-сервисом с помощью SyncAdapter.

Проблема возникает, когда адаптер синхронизации изменяет данные поставщика контента, поставщик запускает сетевую синхронизацию при внутреннем вызове getContentResolver(). notifyChange вызывает цикл синхронизации.

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

Как можно, внутри contentprovider, легко сказать, используется ли его клиентским приложением (которое должно инициировать сетевую синхронизацию при модификации) или адаптером синхронизации (который не должен запускать сетевую синхронизацию).

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

Ответы

Ответ 1

Смотрите это видео об использовании REST API в SyncAdapter s.

Обсуждаемый метод заключается в том, чтобы добавить в базу данных множество столбцов флажков метаданных. Это позволяет нам делать 3 вещи.

  • Сами флаги позволяют SyncAdapter определять строки, которые нуждаются в изменениях и каковы эти изменения. Как вы определяете разницу между локально созданной строкой и локально модифицированной строкой? Кроме того, как вы узнаете, какой вызов REST API должен сделать? Если вы просто удаляете строку, как ваш SyncAdapter знает строку, которая будет удалена, если данные теперь исчезли? Вместо этого установите флажок "Должен быть удален", а затем, когда запускается SyncAdapter, он знает, чтобы нажать удаление на сервер.

  • Флаги позволяют тэгу CursorAdapter изменять созданное представление (например, добавить Spinner, чтобы показать, что "Эта строка синхронизируется" )

  • Наконец, и это они не указывают, флаги позволяют вам объяснить, почему строка изменяется. Если ни один из флагов не установлен, и строка изменяется, это должно быть из-за обновления с сервера. Поэтому нет необходимости синхронизировать с сетью.

Итак, два рабочих процесса:

Локальное изменение

  • Приложение создает новую строку. Строка "create" - это true.
  • ContentProvider сохраняет строку, видит флаг создания и поэтому вызывает notifyChange(...,true);
  • Синхронизация с сетью = истина (последний параметр) вызывает SyncAdapter для запуска.
  • SyncAdapter сканирует базу данных, находит строку с установленным флагом создания и выполняет соответствующее действие сервера. После успеха SyncAdapter очищает флаг. (Обновление строки на ContentProvivder)
  • ContentProvider видит флаг прозрачным, флаги не установлены, поэтому он вызывает notifyChange (..., false);
  • ContentObserver см. изменение флага, обновление выглядит так, как будто "завершена синхронизация"

Все эти шаги эквивалентны для update/delete - по одному флагу для каждой строки синхронизации для каждого из create/update/delete. Также обратите внимание на другую победу - что, если "Создать" не удается временно? сервер вниз... Как вы знаете, чтобы повторить попытку? - Простой, вы не очищаете флаг "Создать", и вы видите его через 15 минут.

Удаленное изменение

  • SyncAdapter срабатывает из-за периодической синхронизации.
  • SyncAdapter извлекает обновление с сервера. Вносит изменения в базу данных. Не устанавливает флаги. ContentProvider видит недостаток флагов, знает, что изменение должно было произойти с сервера (или это не изменение базы данных, которое нужно отправить на сервер), поэтому он вызывает notifyChange(...,false);
  • ContentObserver см. изменение содержимого и поэтому они обновляются с новыми данными строки