简体   繁体   English

Android RecyclerView 未在 adapter.notifyDataSetChanged 上刷新

[英]Android RecyclerView not refreshing on adapter.notifyDataSetChanged

Classic problem here: I'm fetching some data from a database into a recyclerView using an ArrayList of custom objects (and this happens in a Fragment, not in the Main Activity).这里的经典问题:我正在使用自定义对象的 ArrayList 将数据库中的一些数据提取到 recyclerView 中(这发生在片段中,而不是在主活动中)。 Everything works like a charm until I try to refresh the recyclerView using a spinner that changes how the data is sorted.在我尝试使用更改数据排序方式的微调器刷新 recyclerView 之前,一切都像魅力一样工作。 I know the data is fed to the recyclerView correctly.我知道数据已正确输入到 recyclerView。 What am I doing wrong?我究竟做错了什么? API level is 19. API 等级为 19。

This is how the fetch is done:这是获取的方式:

    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;
    }

The fragment with the data being pulled, the recyclerView being set up and with the spinner onItemSelected code:提取数据的片段,正在设置 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;
    }

What I've noticed is that I can get refreshed recyclerView if I replace:我注意到的是,如果我更换,我可以刷新 recyclerView:

adapter.notifyDataSetChanged();

with

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

But that doesn't seem right.但这似乎不对。 I should be able to refresh the existing adapter with new data instead of creating a brand new adapter, correct?我应该能够用新数据刷新现有适配器,而不是创建一个全新的适配器,对吗?

This is a classic issue faced by many developers frequently.这是很多开发者经常面临的经典问题。

Quick Fix:快速解决:

Replace代替

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

with

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

And same for Ascending Order also.升序也一样。

Explanation:解释:

When you initialize the Adapter, you pass an Arraylist whose instance is stored by the Adapter.初始化适配器时,您传递了一个 Arraylist,其实例由适配器存储。 When you call notifyDataSetChanged(), Adapter reads the instance and refreshes the layout as per the new ArrayList.当您调用 notifyDataSetChanged() 时,适配器会根据新的 ArrayList 读取实例并刷新布局。 However, when you reinitialize the ArrayList with sets = dbManager.getSets("order by pieces desc");但是,当您使用sets = dbManager.getSets("order by pieces desc"); , the adapter loses the reference to the new list and is unable to refresh the layout. ,适配器会丢失对新列表的引用并且无法刷新布局。 This can be fixed by keeping the instance the same and replacing the values which are done using clear() and addAll(list) .这可以通过保持实例相同并替换使用clear()addAll(list)完成的值来解决。

Feel free to ask for any doubts in comments and please mark this answer correct if I am able to solve your problem.随时在评论中提出任何疑问,如果我能够解决您的问题,请将此答案标记为正确。

Inside your adapter class create method:在您的适配器class内部创建方法:

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

and then just replace adapter.notifyDataSetChanged() with adapter.setData(sets)然后只需将adapter.notifyDataSetChanged()替换为adapter.setData(sets)

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

相关问题 使用adapter.notifyDataSetChanged()更新RecyclerView - Updating RecyclerView with adapter.notifyDataSetChanged() adapter.notifyDataSetChanged 不刷新回收站视图 - adapter.notifyDataSetChanged does not refreshing the recycler view 尽管我使用了Adapter.notifyDataSetChanged(),但在更改数据集后,Android ListView不会刷新 - Android ListView not refreshing after dataset changed, though I have used the Adapter.notifyDataSetChanged() 取消adapter.notifyDataSetChanged - Cancel adapter.notifyDataSetChanged Android:adapter.registerDataSetObserver与adapter.notifyDatasetChanged - Android: adapter.registerDataSetObserver vs adapter.notifyDatasetChanged Android-为什么要使用adapter.notifydatasetChanged()方法? - Android - Why should we use adapter.notifydatasetChanged() method? 我的adapter.notifyDataSetChanged()不起作用 - My adapter.notifyDataSetChanged() is not working 从另一个线程调用adapter.notifyDataSetChanged() - Call adapter.notifyDataSetChanged() from another thread adapter.notifyDatasetChanged()无需更改当前视图 - adapter.notifyDatasetChanged() without changing current view Adapter.notifyDataSetChanged()在onCreate()中不起作用 - Adapter.notifyDataSetChanged() not working inside onCreate()
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM