【问题标题】:Android RecyclerView not refreshing on adapter.notifyDataSetChangedAndroid RecyclerView 未在 adapter.notifyDataSetChanged 上刷新
【发布时间】:2020-05-13 11:45:55
【问题描述】:

这里的经典问题:我正在使用自定义对象的 ArrayList 将一些数据从数据库中提取到 recyclerView 中(这发生在 Fragment 中,而不是 Main Activity 中)。在我尝试使用更改数据排序方式的微调器刷新 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);

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

【问题讨论】:

    标签: java android android-recyclerview


    【解决方案1】:

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

    快速修复:

    替换

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

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

    升序也一样。

    说明:

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

    如果对 cme​​ts 有任何疑问,请随时提问,如果我能够解决您的问题,请将此答案标记为正确。

    【讨论】:

    • 完美运行!谢谢,这么简单的错误!
    【解决方案2】:

    在您的适配器内部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)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-24
      • 2017-11-11
      • 2015-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-28
      相关资源
      最近更新 更多