繁体   English   中英

Android RecyclerView 未在 adapter.notifyDataSetChanged 上刷新

[英]Android RecyclerView not refreshing on adapter.notifyDataSetChanged

这里的经典问题:我正在使用自定义对象的 ArrayList 将数据库中的一些数据提取到 recyclerView 中(这发生在片段中,而不是在主活动中)。 在我尝试使用更改数据排序方式的微调器刷新 recyclerView 之前,一切都像魅力一样工作。 我知道数据已正确输入到 recyclerView。 我究竟做错了什么? API 等级为 19。

这是获取的方式:

    public ArrayList<LEGOSet> getSets(String conditions) {
        ArrayList<LEGOSet> sets = new ArrayList<>();

        Cursor cursor = database.rawQuery("SELECT * FROM Sets " + conditions, null);
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
                LEGOSet set = new LEGOSet(cursor.getInt(0), cursor.getString(1), cursor.getInt(2), cursor.getInt(3), cursor.getString(4), cursor.getDouble(5),
                    cursor.getDouble(6), cursor.getDouble(7), cursor.getDouble(8), cursor.getDouble(9), cursor.getDouble(10), cursor.getString(11),
                    cursor.getString(12), cursor.getString(13), cursor.getString(14), cursor.getInt(15), cursor.getInt(16), cursor.getInt(17));
            sets.add(set);
            cursor.moveToNext();
        }
        cursor.close();
        return sets;
    }

提取数据的片段,正在设置 recyclerView 和微调器 onItemSelected 代码:

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_catalog, container, false);

        // pull data from database
        sets = dbManager.getSets("order by pieces desc");

        // set up the RecyclerView
        final RecyclerView recyclerView = root.findViewById(R.id.rvSets);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        adapter = new MyRecyclerViewAdapter(getActivity(), sets, portrait);
        adapter.setClickListener(this);
        recyclerView.setAdapter(adapter);

        // add dividers
        DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), 1);
        dividerItemDecoration.setDrawable(new ColorDrawable(getResources().getColor(R.color.colorSubtle)));
        recyclerView.addItemDecoration(dividerItemDecoration);

        // spinner Product Sorting
        spinnerProductSorting = root.findViewById(R.id.spinnerProductSorting);
        spinnerProductSorting.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
                String s = spinnerProductSorting.getSelectedItem().toString();

                switch(s)
                {
                    case "Biggest first":
                        sets = dbManager.getSets("order by pieces desc");
                        Toast.makeText(getContext(),sets.get(0).getName(), Toast.LENGTH_SHORT).show();
                        break;
                    case "Smallest first":
                        sets = dbManager.getSets("order by pieces asc");
                        Toast.makeText(getContext(),sets.get(0).getName(), Toast.LENGTH_SHORT).show();
                        break;
                    default:
                }
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {}
        });


        disclaimer = root.findViewById(R.id.disclaimer);
        disclaimer.setMovementMethod(LinkMovementMethod.getInstance());

        return root;
    }

我注意到的是,如果我更换,我可以刷新 recyclerView:

adapter.notifyDataSetChanged();

adapter = new MyRecyclerViewAdapter(getActivity(), sets, portrait);
recyclerView.setAdapter(adapter);

但这似乎不对。 我应该能够用新数据刷新现有适配器,而不是创建一个全新的适配器,对吗?

这是很多开发者经常面临的经典问题。

快速解决:

代替

sets = dbManager.getSets("order by pieces desc");

sets.clear()
sets.addAll(dbManager.getSets("order by pieces desc"));

升序也一样。

解释:

初始化适配器时,您传递了一个 Arraylist,其实例由适配器存储。 当您调用 notifyDataSetChanged() 时,适配器会根据新的 ArrayList 读取实例并刷新布局。 但是,当您使用sets = dbManager.getSets("order by pieces desc"); ,适配器会丢失对新列表的引用并且无法刷新布局。 这可以通过保持实例相同并替换使用clear()addAll(list)完成的值来解决。

随时在评论中提出任何疑问,如果我能够解决您的问题,请将此答案标记为正确。

在您的适配器class内部创建方法:

setData(ArrayList<LEGOSet> sets) {  // new list here
    this.sets = sets;  // assing ArrayList from database to your list which is inside adapter class
    notifyDataSetChanged();
}

然后只需将adapter.notifyDataSetChanged()替换为adapter.setData(sets)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM