Метод ContentObserver onChange() вызывается много раз

У меня есть требование отслеживать любой новый файл изображения типа .jpg, созданный на устройстве. Я сделал это, используя ContentObserver на MediaStore, используя класс MediaStoreObserver ниже, и зарегистрировал то же самое в одном из моих сервисов.

Я заметил, что метод onChange() вызывается много раз для создания одного файла. Я понимаю, что созданный медиафайл обновляется во многих таблицах MediaStore, поэтому onChange() вызывается много раз.

Мой вопрос: Как зарегистрироваться на MediaStore ТОЛЬКО для операции создания/редактирования файла изображения?

- Заранее спасибо, Манджу.

    private class MediaStoreObserver extends ContentObserver {
    public MediaStoreObserver() {
        super(null);
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);

        //check image file changes in MediaStore
        readFromMediaStore(_context,MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    }
}

//register for external media changes for image files
if(mediaStoreObserver!=null){
  _context.getContentResolver().registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
        false,mediaStoreObserver);

person Manju    schedule 25.02.2014    source источник
comment
Где вы отменили регистрацию этого наблюдателя?? Если вы не проверили, регистрирует ли ваш код этот наблюдатель несколько раз.   -  person Pankaj Kumar    schedule 25.02.2014
comment
Это регистрируется в службе onCreate(), и то же самое отменяется в onDestroy() моей службы.   -  person Manju    schedule 25.02.2014


Ответы (2)


Короткий ответ: вы не можете, это поставщик, который отправляет notifyChange (полученный с наблюдателями onChange) всякий раз, когда что-то: обновляется/вставляется/удаляется

Подробный ответ: это то, что нужно сделать для достижения того, чего вы хотите (как зарегистрироваться в MediaStore ТОЛЬКО для операции создания/редактирования файла изображения?):

Считайте таблицу изображений из MediaStore при запуске и сохраните столбец _data (пути к файлам) в отсортированном collection, отсортированном collection с путями (строками). И всякий раз, когда вы получаете вызов onChange, создайте новую коллекцию вышеуказанного вида, затем перебирайте новую коллекцию и ищите исходную коллекцию, которую вы создали, с помощью двоичного поиска (поскольку коллекция отсортирована, и мы хотим сохранить низкую временную сложность). Это привело бы к довольно эффективной реализации со временем работы O(n*logn).

Или в псевдокоде:

1. Read current image columns from media store (the `_data column as projection)
2. Store result in a collection, with string type
3. Sort collection
4. Upon `onChange` is received, make a new collection as step 1-3
5. Loop over collection created in 4 and search each string you take out with 
binary search in the sorted collection you got from step 3, if item is not found 
then the item is new
6. Make the collection in 4 the current cached version of mediastore 
7. Time complexity is O(n*log n) for the above algorithm 

Редактировать для обновленной файловой части. Я бы читал поле даты изменения из MediaStore всякий раз, когда мой поиск на шаге 5 срабатывает, это будет означать, что вы должны фактически сохранить как файл (uri), так и дату изменения< /strong> в классе данных, но для поиска используйте путь к файлу. Всякий раз, когда файл найден, вы должны проверить, совпадают ли измененные даты, если нет, то это обновленный файл.

person Magnus    schedule 28.02.2014

У меня была такая же проблема, и я исправил ее, удалив super.onchange из моего переопределения onchange.

person user3886197    schedule 29.07.2014
comment
Это не работает для меня. Когда я это делаю, я получаю ANR. - person barq; 13.07.2015