SyncAdapter использует только последние дополнения для нескольких вызовов requestSync ()

Я использую SyncAdapter и GCM, чтобы уведомлять свое приложение о различных типах изменений на внутреннем сервере. Например, если на сервере происходит изменение A, я отправляю push-уведомление с помощью поля с именем change_a, которое передаю от SyncAdapter до ContentResolver.requestSync(). Таким образом, SyncAdapter знает, что синхронизировать с сервера. Точно так же для изменения B я отправляю поле с именем change_b.

Это отлично работает, за исключением одного варианта использования. Я отправляю уведомление change_a, оно вызывает ContentResolver.requestSync(), но из-за отсутствия доступности сети SyncAdapter еще не вызывается. Если после этого я отправляю уведомление change_b, снова вызывается ContentResolver.requestSync() с новым полем. А затем, когда сеть активна, вызывается SyncAdapter, но только с последним полем change_b и, соответственно, он не будет синхронизировать изменение A.

Таким образом, в основном ContentResolver.requestSync() отменяет все предыдущие requestSync() вызовы, которые еще не активировали SyncAdapter. SyncAdapter работает с последними отправленными дополнениями.

Одно из решений - не различать изменение A и изменение B и SyncAdapter синхронизировать все. Но это дорого обходится полосе пропускания. Я хочу контролировать, что и когда синхронизировать. Есть ли что-то, что я могу сделать, чтобы это исправить (возможно, флаг syncadapter)?


person Catalin Morosan    schedule 10.11.2012    source источник
comment
Сохраните поле (_a, _b и т. Д.) В общих настройках / sqlite при срабатывании адаптера синхронизации, удалите после успешной синхронизации - при обнаружении неудачной попытки синхронизации _a при срабатывании для _b проблема должна быть решена.   -  person Jens    schedule 10.11.2012
comment
да. Я думал об этом решении. Но я надеялся на что-нибудь полезное в API. Если нет другого пути, я выберу этот.   -  person Catalin Morosan    schedule 10.11.2012
comment
Что ж, вы всегда можете просто подклассифицировать свой адаптер синхронизации и зарегистрировать один для синхронизации _a и один для _b, таким образом, новый запрос-синхронизация для _b не будет мешать повторным попыткам для _a.   -  person Jens    schedule 10.11.2012
comment
Вы используете разные клавиши сворачивания для изменений a и b?   -  person NickT    schedule 10.11.2012
comment
@NickT Нет. Но с этого момента я обязательно буду использовать. Проверьте мой ответ ниже.   -  person Catalin Morosan    schedule 11.11.2012


Ответы (2)


Похоже, я сделал неправильные выводы. Фактически, после некоторого дальнейшего тестирования, если requestSync() вызывается с разными дополнениями, SyncAdapter вызывается несколько раз для каждого отдельного пакета.

Моя проблема была где-то в другом месте. Когда я получал push-уведомление, я бы запланировал срабатывание будильника для запуска запроса синхронизации, и я бы использовал PendingIntent с флагом PendingIntent.FLAG_CANCEL_CURRENT, что означало, что если другое push-уведомление придет до того, как сработает будильник, будильник будет перезаписан новые данные. Итак, если устройство было в автономном режиме, когда оно подключалось к сети, оно получало все ожидающие push-уведомления, и был бы установлен только один сигнал тревоги с данными из самого последнего push-уведомления.

Я решил эту проблему, установив разные действия для каждого PendingIntent, чтобы установка нового сигнала тревоги того же типа не перезаписывала другие типы сигналов тревоги.

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

person Catalin Morosan    schedule 11.11.2012

Похоже, я сделал неправильные выводы. Фактически, после некоторого дальнейшего тестирования, если requestSync () вызывается с разными дополнительными функциями, SyncAdapter вызывается несколько раз для каждого отдельного Bundle.

Если вы используете разные дополнения в нескольких вызовах requestSync(), то performSync() будет вызываться для каждого requestSync(). Я хочу добавить доказательство: вызов toKey() внутри SyncOperation.java включает значения из пакета дополнительных услуг. Это предотвращает SyncManager дедупликацию этих SyncOperations.

person Brian Attwell    schedule 30.10.2013