![](/img/trans.png)
[英]Updating RecyclerView with 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.