Как сохранить позицию 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();
}

И все это будет поддерживать вашу позицию прокрутки точно: -)