使用新的Loader API时如何维护ListView位置?

时间:2011-08-28 00:11:17

标签: android cursor android-listview android-support-library

在Honeycomb中,Loader API被引入作为通过在后台线程上进行繁重工作来向应用程序提供数据的正确方法。在我的应用程序中,我正在努力将所有Cursor替换为Loader,返回Cursor s。由于Cursor.requery()现已弃用,因此建议您只需调用restartLoader并允许再次在后台线程上完成工作,然后在changeCursor中返回时onLoadFinished

所有这一切都非常有效,除了当我想重新查询数据时ListView没有保持它的滚动位置,使用Cursor.requery()这用来工作,因为它是与更新数据相同的Cursor实例。

如何在不丢失滚动位置的情况下刷新Loader?

2 个答案:

答案 0 :(得分:6)

Loader类本身不知道数据集何时更改,并且当前是CursorLoader特定于实现的。现在在我的应用程序中,我需要刷新的数据位于本地SQLite数据库(没有ContentProvider)内,因此我必须修改CursorLoader以使用我的本地数据库,正如Dianne Hackborne在developer group中提到的那样。

不幸的是,从loadInBackground返回一个Cursor不允许ContentObserver在数据发生变化时正确通知Loader,这是因为AbstractCursor仅在notifyChanged()时调用requery() }在Cursor上调用。

由于ContentObserver永远不会通知Loader数据已发生变化,我最终会根据需要自行调用Loader.onContentChanged()。在这一点上,它似乎一切正常,但如果出现任何重大问题,我会更新这个答案。

答案 1 :(得分:1)

您必须在每个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);
        }
    }

在你的适配器中创建一个方法来重新填充项目

public void refill(List<NotificationItem> notifications) {
    mNotificationsList.clear();
    mNotificationsList.addAll(notifications);
    notifyDataSetChanged();
}

就是这样,它会完全保持你的滚动位置: - )