ContentObserver вызывается даже при отсутствии изменений в курсоре

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

private static final Uri MYAPP_CONTENT_URI = ContactsContract.RawContacts.CONTENT_URI.buildUpon().appendQueryParameter(RawContacts.ACCOUNT_NAME, SyncAdapter.MYAPP_ACCOUNT_NAME).appendQueryParameter(RawContacts.ACCOUNT_TYPE, MY_APP_ACCOUNT_TYPE).build();

public static void registerContentObserver() {
    ContentResolver resolver = MyApplication.getAppContext().getContentResolver();
    cursorContacts = resolver.query(MYAPP_CONTENT_URI, null, RawContacts.DELETED + "=0", null, null);
    cursorContacts.registerContentObserver(MYAPP_URI_OBSERVER);
}

public static void unregisterContentObserver() {
    if (cursorContacts != null) {
        cursorContacts.unregisterContentObserver(MYAPP_URI_OBSERVER);
        cursorContacts.close();
    }
}

Проблема в том, что даже когда курсор пуст (getCount возвращает 0), после регистрации наблюдателя я получаю вызов onChange, что бы я ни делал в собственной адресной книге. Разве наблюдатель не должен вызываться только тогда, когда одна из записей в курсоре была изменена? В документации указано:

Зарегистрируйте наблюдателя, который вызывается, когда происходят изменения в содержимом, поддерживающем этот курсор.

Что такое «контент, поддерживающий этот курсор»? Я думал, что это список поиска контактов в курсоре, но похоже, что достаточно изменить ContactsContract.RawContacts.CONTENT_URI.

Я также попытался зарегистрировать одного наблюдателя для каждого Uri. Это не помогает. Хотя в документации для ContentResolver.registerContentObserver указано:

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

Parameters
        uri  The URI to watch for changes. This can be a specific row URI, or a base URI for a whole class of content. 
        notifyForDescendents  If true changes to URIs beginning with uri will also cause notifications to be sent. If false only changes to the exact URI specified by uri will cause notifications to be sent. If true, than any URI values at or below the specified URI will also trigger a match. 

(Я установил для notifyForDescidents значение false, но в любом случае он не должен был вызывать наблюдателей).

Что случилось? Спасибо


person kingston    schedule 07.02.2012    source источник


Ответы (2)


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

person hackbod    schedule 25.02.2012
comment
так почему в документации сказано что-то другое? - person kingston; 28.02.2012

Параметры запроса в вашем Uri, фрагменте или даже схеме учитываются, когда происходит сопоставление Observer Uri. Единственное, что имеет значение, это авторитет Ури и сегменты пути. Происходит строгое сопоставление слева направо. Я не проверял "*" в сегменте пути для обозначения подстановочного знака, но подозреваю, что это не сработает.

Ваш конкретный наблюдатель — ContactsContract.RawContacts.CONTENT_URI, поэтому каждый раз, когда по какой-либо причине изменяется содержимое любого контакта, ваш наблюдатель срабатывает.

person Uncle Code Monkey    schedule 15.03.2014