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

У меня андроид ListActivity который опирается на базу данных Cursor через SimpleCursorAdapter,

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

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

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

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

6 ответов

Решение

Вызов requery() на Cursor когда вы меняете данные в базе данных, которые вы хотите отразить в этом 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...

Другие вопросы по тегам