ContentResolver.notifyChange () не работает - PullRequest
3 голосов
/ 09 октября 2011

Некоторая справочная информация:

Когда я запускаю свое приложение, приоритетное действие отображает кэшированную информацию из моей локальной базы данных SQLite, и тем временем фоновая служба подключается к серверу и получает некоторую свежую информацию. Когда данные извлекаются, служба запускает метод вставки моего ContentProvider, чтобы обновить мою локальную базу данных SQLite. Когда вставка завершена, я уведомляю свой ContentObserver (действие переднего плана) об изменении, чтобы обновить представление.

Я знаю, что вставка работает нормально, потому что когда я запускаю приложение вручную, я вижу новые данные на моем экране. К сожалению, автообновление не работает. Вызов метода ContentObserver.notifyChange() завершается неудачно. Самое странное, что он даже не останавливается на линии catch (Exception e). Он идет прямо за пределы блока try/catch. Я понятия не имею, что происходит. LogCat и консоль тихие.

Вот часть кода из метода insert в моем ContentProvider, отвечающая за вставку и уведомление об изменении.

SQLiteDatabase sqlDB = db.getWritableDatabase();
try {
    long newID = sqlDB.insertOrThrow(StatsCollectorDatabase.TABLE_USERS, null, values);
    if (newID > 0) {
        Uri newUri = ContentUris.withAppendedId(uri, newID);
        ContentResolver contentResolver = getContext().getContentResolver();
        contentResolver.notifyChange(uri, null); // This is the line that fails
        return newUri;
    } else {
        throw new SQLException("Failed to insert row into " + uri);
    }
} catch (SQLiteConstraintException e) {
    Log.i(DEBUG_TAG, "Ignoring constraint failure.");
} catch (Exception e) {
    Log.i(DEBUG_TAG, e.getLocalizedMessage());
}

Вот код из onCreate метода на переднем плане. Упражнение:

Cursor cursor = this.managedQuery(StatsCollectorProvider.CONTENT_URI, null, null, null, null);
String[] columns = new String[] { StatsCollectorDatabase._USER_NAME, StatsCollectorDatabase._USER_DEVICE_ID };
int[] views = new int[] { R.id.name_entry, R.id.number_entry };

SimpleCursorAdapter adapter = new SimpleCursorAdapter(this.getApplicationContext(), R.layout.list_item, cursor, columns, views, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
this.setListAdapter(adapter);

Intent intent = new Intent(this.getApplicationContext(), UsersDownloaderService.class);
this.startService(intent);    

Я попытался поискать в Google, но ничего не нашел. Как мне решить эту проблему?

Я могу предоставить больше кода, если это понадобится.

Ответы [ 2 ]

2 голосов
/ 16 октября 2011

Я решил это.Моя деятельность не наследовала FragmentActivity, и мой макет не содержал никаких фрагментов, поэтому он не мог работать - не было никаких зарегистрированных ContentObservers.

Теперь это выглядит так:

Сначалаосновное действие начинается, регистрируя макет фрагмента и запуская фоновый сервис в его onCreate методе:

super.onCreate(savedInstanceState);
setContentView(R.layout.list);

Intent intent = new Intent(this.getApplicationContext(), UsersDownloaderService.class);
this.startService(intent);  

Это мой list макет:

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    class="org.moyshe.cursors.ListViewFragment"
    android:name="org.moyshe.cursors.ListViewFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</fragment>

Класс ListViewFragment расширяет ListFragment и реализует LoaderCallbacks<Cursor>.Это мой ContentObserver, который я пропустил.Если кому-то интересно, как он выглядит, прочитайте эту статью - она ​​мне очень помогла.

Мои классы Service и ContentProvider не изменились.

1 голос
/ 20 декабря 2014

У меня похожая проблема, и я нашел решение здесь .

Короче говоря, оказалось, что мне нужно вызвать setNotificationUri(ContentResolver cr, Uri uri) для курсора, возвращаемого методом query() моего провайдера контента.

...