Как сохранить позицию ListView при использовании новых API-интерфейсов Loader?
В Honeycomb API-интерфейсы Loader были введены в качестве надлежащего способа предоставления данных в приложение, делая тяжелый подъем на фоновом потоке. В моем приложении я работаю, чтобы заменить все мои Cursor
на Loader
, которые возвращают Cursor
s. Поскольку Cursor.requery()
обесценивается сейчас, рекомендуется просто вызвать restartLoader
и разрешить повторную работу снова в фоновом потоке, а затем changeCursor
, когда он вернется в onLoadFinished
.
Все это прекрасно работает, за исключением того, что ListView не поддерживает его прокрутку позиции, когда я хочу запрашивать данные, используя Cursor.requery()
, который использовался для работы, потому что это был тот же экземпляр курсора с обновленными данными.
Как обновить мой загрузчик, не потеряв положение прокрутки?
Ответы
Ответ 1
Класс Loader
сам по себе не знает, когда изменяется набор данных и в настоящее время используется для реализации CursorLoader
. Теперь в моем приложении данные, которые мне нужно обновить, находятся внутри локальной базы данных SQLite (без ContentProvider), поэтому мне пришлось изменить CursorLoader
, чтобы вместо этого использовать мою локальную базу данных, как упоминала Dianne Hackborne на группа разработчиков.
К сожалению, просто возврат курсора из loadInBackground не позволяет ContentObserver
правильно уведомлять загрузчик при изменении данных, это связано с тем, что AbstractCursor
вызывает только notifyChanged()
, когда requery()
вызывается в курсоре.
Так как ContentObserver
никогда не будет уведомлять Loader
о том, что данные были изменены, я в конечном итоге вызывал Loader.onContentChanged()
сам по мере необходимости. На данный момент все работает, но я обновляю этот ответ, если возникнут какие-либо существенные проблемы.
Ответ 2
Вы должны просто не создавать новый адаптер в каждой загрузке Loaders; Я имею в виду..
@Override
public void onLoadFinished(Loader<List<NotificationItem>> loader, List<NotificationItem> notifications) {
// We must do it in this way to not losing listview scroll position after a reload.
if(mAdapter==null) {
mAdapter = new HomeUserActivityListAdapter(getActivity(), notifications);
mListView.setAdapter(mAdapter);
}else{
mAdapter.refill(notifications);
}
}
И в вашем адаптере создайте метод для пунктов refill
public void refill(List<NotificationItem> notifications) {
mNotificationsList.clear();
mNotificationsList.addAll(notifications);
notifyDataSetChanged();
}
И все это будет поддерживать вашу позицию прокрутки точно: -)