Android SimpleCursorAdapter не обновляется при изменении базы данных

У меня есть Android ListActivity который поддерживается базой данных Cursor через SimpleCursorAdapter .

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

Проблема в том, что когда обновленное представление выходит за пределы экрана и перерабатывается, старое значение отображается в представлении, когда оно возвращается в представление. То же самое происходит всякий раз, когда список новостей перерисовывается (изменения ориентации и т. Д.).

Я использую notifydatasetchanged() для обновления адаптера курсора, но он кажется неэффективным.

Как я должен обновлять базу данных, чтобы курсор также обновлялся?

Solutions Collecting From Web of "Android SimpleCursorAdapter не обновляется при изменении базы данных"

Call requery() при изменении данных в базе данных, которые вы хотите отразить в этом Cursor (или вещи, которые заполняет Cursor , например ListView через CursorAdapter ).

Cursor похож на курсор на стороне клиента ODBC – он содержит все данные, представленные результатом запроса. Следовательно, только потому, что вы меняете данные в базе данных, Cursor не будет знать об этих изменениях, если вы не обновите его через requery() .


ОБНОВЛЕНИЕ : весь этот вопрос и набор ответов следует удалить из-за старости, но это, по-видимому, невозможно. Любой, кто ищет ответы на Android, должен иметь в виду, что Android – стремительно движущаяся цель, а ответы с 2009 года, как правило, хуже, чем более новые ответы.

Текущим решением является получение свежего Cursor и использование changeCursor() или swapCursor() в CursorAdapter для изменения данных.

requery теперь устарел. Из документации :

Этот метод устарел. Не используйте это. Просто запросите новый курсор, чтобы вы могли сделать это асинхронно и обновить представление списка после возвращения нового курсора.

После получения нового курсора можно использовать adapter.changeCursor(cursor) . Это должно обновить представление.

В случае использования загрузчика и автоматически созданного курсора вы можете позвонить:

 getLoaderManager().restartLoader(0, null, this); 

В вашей деятельности, сразу после изменения чего-либо в БД, для восстановления нового курсора. Не забудьте также определить обработчики событий:

 @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { CursorLoader cursorLoader = new CursorLoader(this, YOUR_URI, YOUR_PROJECTION, null, null, null); return cursorLoader; } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { adapter.swapCursor(data); } @Override public void onLoaderReset(Loader<Cursor> loader) { adapter.swapCursor(null); } 

Непонятно, если вы установите для свойства autoRequery для CursorAdapter значение true .

Адаптер проверяет свойство autoRequery ; Если оно false , то курсор не будет изменен.

Requery () уже устарел, просто реализуйте простой метод updateUI (), подобный этому в вашем дочернем классе CursorAdapter, и вызовите его после обновления данных:

 private void updateUI(){ swapCursor(dbHelper.getCursor()); notifyDataSetChanged(); } 

Это просто.

 private Db mDbAdapter; private Cursor mCursor; private SimpleCursorAdapter mCursorAd; ..................................... //After removing the item from the DB, use this ..................................... mCursor = mDbAdapter.getAllItems(); mCursorAd.swapCursor(mCursor); 

Или используйте CursorLoader …