java 如何在适配器数据更改时更新可扩展列表视图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1463906/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 16:38:00  来源:igfitidea点击:

How to update expandable list view when adapter's data changes

javaandroid

提问by Evgeny Shurakov

I have an activity that extends ExpandableListActivity. I use SimpleCursorTreeAdapter to fill ExpandableListView. My layout contains list view and empty view. On app start ExpandableListActivity automatically chooses the right view to display.

我有一个扩展 ExpandableListActivity 的活动。我使用 SimpleCursorTreeAdapter 来填充 ExpandableListView。我的布局包含列表视图和空视图。在应用程序启动时 ExpandableListActivity 会自动选择要显示的正确视图。

My steps:

我的步骤:

  1. App starts, there is no data. (empty view on the screen)
  2. Insert some data into db.
  3. Call adapter.notifyDataSetChanged(); But empty view is still on the screen and there is no any item in my list view.
  1. 应用程序启动,没有数据。(屏幕上的空白视图)
  2. 将一些数据插入数据库。
  3. 调用 adapter.notifyDataSetChanged(); 但是屏幕上仍然是空视图,我的列表视图中没有任何项目。

Then I restart app:

然后我重新启动应用程序:

  1. List view appears. I expand all groups and scroll to the bottom.
  2. I click on the item in the list. New activity appears.
  3. Click back button. All groups are collapsed and we are at the top of the screen. Scroll position and expanded groups are not remembered.
  4. Delete all data from db and call adapter.notifyDataSetChanged();
  5. Child views have disappeared, but top-level groups are still visible.
  1. 出现列表视图。我展开所有组并滚动到底部。
  2. 我单击列表中的项目。出现新活动。
  3. 单击返回按钮。所有组都折叠起来,我们位于屏幕顶部。不会记住滚动位置和扩展组。
  4. 从数据库中删除所有数据并调用 adapter.notifyDataSetChanged();
  5. 子视图已经消失,但顶级组仍然可见。

Questions:

问题:

  1. What can I do to replace empty view with list view?
  2. What can I do to do to save state of groups and scroll position of the list view?
  1. 我该怎么做才能用列表视图替换空视图?
  2. 我该怎么做才能保存组的状态和列表视图的滚动位置?

Tested on SDKs: 1.5r3, 1.6r1

在 SDK 上测试:1.5r3、1.6r1

Code:

代码:

public class MainActivity extends ExpandableListActivity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        dbHelper = new DBOpenHelper(this);

        rubricsDbAdapter = new RubricsDBAdapter(dbHelper);
        rubricsDbAdapter.open();

        itemsDbAdapter = new ItemsDBAdapter(dbHelper);
        itemsDbAdapter.open();

        rubricsCursor = rubricsDbAdapter.getAllItemsCursor();
        startManagingCursor(rubricsCursor);

        // Cache the ID column index
        rubricIdColumnIndex = rubricsCursor.getColumnIndexOrThrow(RubricsDBAdapter.KEY_ID);

        // Set up our adapter
        mAdapter = new MyExpandableListAdapter(rubricsCursor,
                this,
                android.R.layout.simple_expandable_list_item_1,
                android.R.layout.simple_expandable_list_item_1,
                new String[] {RubricsDBAdapter.KEY_NAME},
                new int[] {android.R.id.text1},
                new String[] {ItemsDBAdapter.KEY_NAME}, 
                new int[] {android.R.id.text1});

        setListAdapter(mAdapter);
    }

    public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
        Intent i = new Intent(this, ItemViewActivity.class);
        i.putExtra(ItemsDBAdapter.KEY_ID, id);
        startActivity(i);

        return super.onChildClick(parent, v, groupPosition, childPosition, id);
    }

    private void updateMyData() {
        int i;
        int k;
        long rubricId;

        for (i = 1; i <= 5; i++) {
            rubricId = rubricsDbAdapter.insert("rubric " + i);
            for (k = 1; k <= 5; k++) {
                itemsDbAdapter.insert("item " + i + "-" + k, rubricId);
            }
        }

        mAdapter.notifyDataSetChanged();
    }

    private void deleteMyData() {
        rubricsDbAdapter.deleteAll();
        itemsDbAdapter.deleteAll();

        mAdapter.notifyDataSetChanged();
    }

    public class MyExpandableListAdapter extends SimpleCursorTreeAdapter 
    {
        public MyExpandableListAdapter(Cursor cursor, Context context, int groupLayout,
                int childLayout, String[] groupFrom, int[] groupTo, String[] childrenFrom,
                int[] childrenTo) {
            super(context, cursor, groupLayout, groupFrom, groupTo, childLayout, childrenFrom,
                    childrenTo);
        }

        @Override
        protected Cursor getChildrenCursor(Cursor notebookCursor) {
            // Given the group, we return a cursor for all the children within that group 
            long id = notebookCursor.getLong(rubricIdColumnIndex);

            Cursor itemsCursor = itemsDbAdapter.getRubricItemsCursor(id);
            startManagingCursor(itemsCursor);
            return itemsCursor;
        }

    }
}

采纳答案by Evgeny Shurakov

So, the answer is:

所以,答案是:

  1. Call cursor.requery() before calling adapter's notifyDataSetChanged() method.
  2. Save groups state in activity's onPause() method and restore in onResume() method.
  1. 在调用适配器的 notifyDataSetChanged() 方法之前调用 cursor.requery()。
  2. 在活动的 onPause() 方法中保存组状态并在 onResume() 方法中恢复。

回答by MaTT

Re: Question # 2...

回复:问题#2...

Why can't you simply call View.invalidateViews() and View.requestLayout() in that order?

为什么不能简单地按这个顺序调用 View.invalidateViews() 和 View.requestLayout() ?

If you already have your adapter set to the view, then you shouldn't need to requery, do you? By invalidating the view, and requesting the layout, you won't lose any of the states of your view.

如果您已经将适配器设置为视图,那么您不需要重新查询,对吗?通过使视图无效并请求布局,您不会丢失视图的任何状态。

For example, in your "onResume" method, invalidate your list view by calling something like "lv.invalidateViews()". Next, call "lv.requestLayout()".

例如,在您的“onResume”方法中,通过调用“lv.invalidateViews()”之类的方法使您的列表视图无效。接下来,调用“lv.requestLayout()”。

Your "onCreate" method should still be responsible for setting up the adapters and linking an adapter to the view. To link the adapter, consider using "lv.setListAdapter()" instead of the former so that you aren't messing with the other views on the screen.

您的“onCreate”方法仍应负责设置适配器并将适配器链接到视图。要链接适配器,请考虑使用“lv.setListAdapter()”而不是前者,以免干扰屏幕上的其他视图。