У меня есть Android ListActivity
, который поддерживается базой данных Cursor
через SimpleCursorAdapter
.
При щелчке по элементам поле флажка в соответствующей строке в базе данных переключается, и представление в списке необходимо обновить.
Проблема заключается в том, что когда обновленное представление выходит из экрана и перерабатывается, старое значение отображается в представлении, когда оно возвращается в представление. То же самое происходит всякий раз, когда предикат перерисовывается (изменения ориентации и т.д.).
Я использую notifydatasetchanged()
для обновления адаптера курсора, но он кажется неэффективным.
Как мне обновлять базу данных, чтобы курсор также обновлялся?
Вызов requery()
в Cursor
при изменении данных в базе данных, которые вы хотите отразить в этом Cursor
(или вещи, которые Cursor
заполняет, например, ListView
через CursorAdapter
).
A 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
, то курсор не будет изменен.
protected void init (Context context, Cursor c, boolean autoRequery)
Этот метод устарел. Не используйте это, используйте обычный конструктор. Это будет удалено в будущем.
Это легко.
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...
requery() уже устарел, просто реализуйте простой метод updateUI(), подобный этому в дочернем классе CursorAdapter, и вызовите его после обновления данных:
private void updateUI(){
swapCursor(dbHelper.getCursor());
notifyDataSetChanged();
}