如何更新RecyclerView适配器数据?
4天,我无法弄清楚什么是更新RecyclerView
的适配器的问题。
我得到一个新的产品清单后,我试图:
-
从创build
recyclerView
的片段更新ArrayList
,将新数据设置为适配器,然后调用adapter.notifyDataSetChanged()
; 它不起作用。 -
创build一个新的适配器,像其他人一样,它为他们工作,但没有改变:
recyclerView.setAdapter(new RecyclerViewAdapter(newArrayList))
-
在
Adapter
创build一个方法来更新数据,如下所示:public void updateData(ArrayList<ViewModel> viewModels) { items.clear(); items.addAll(viewModels); notifyDataSetChanged(); }
然后,每当我想更新数据列表时,我都会调用这个方法; 它不起作用。
-
要检查我是否可以以任何方式修改recyclerView,并试图删除至less一个项目:
public void removeItem(int position) { items.remove(position); notifyItemRemoved(position); }
一切都保持原样。
这是我的适配器:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> implements View.OnClickListener { private ArrayList<ViewModel> items; private OnItemClickListener onItemClickListener; public RecyclerViewAdapter(ArrayList<ViewModel> items) { this.items = items; } public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.onItemClickListener = onItemClickListener; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycler, parent, false); v.setOnClickListener(this); return new ViewHolder(v); } public void updateData(ArrayList<ViewModel> viewModels) { items.clear(); items.addAll(viewModels); notifyDataSetChanged(); } public void addItem(int position, ViewModel viewModel) { items.add(position, viewModel); notifyItemInserted(position); } public void removeItem(int position) { items.remove(position); notifyItemRemoved(position); } @Override public void onBindViewHolder(ViewHolder holder, int position) { ViewModel item = items.get(position); holder.title.setText(item.getTitle()); Picasso.with(holder.image.getContext()).load(item.getImage()).into(holder.image); holder.price.setText(item.getPrice()); holder.credit.setText(item.getCredit()); holder.description.setText(item.getDescription()); holder.itemView.setTag(item); } @Override public int getItemCount() { return items.size(); } @Override public void onClick(final View v) { // Give some time to the ripple to finish the effect if (onItemClickListener != null) { new Handler().postDelayed(new Runnable() { @Override public void run() { onItemClickListener.onItemClick(v, (ViewModel) v.getTag()); } }, 0); } } protected static class ViewHolder extends RecyclerView.ViewHolder { public ImageView image; public TextView price, credit, title, description; public ViewHolder(View itemView) { super(itemView); image = (ImageView) itemView.findViewById(R.id.image); price = (TextView) itemView.findViewById(R.id.price); credit = (TextView) itemView.findViewById(R.id.credit); title = (TextView) itemView.findViewById(R.id.title); description = (TextView) itemView.findViewById(R.id.description); } } public interface OnItemClickListener { void onItemClick(View view, ViewModel viewModel); } }
我启动RecyclerView
如下:
recyclerView = (RecyclerView) view.findViewById(R.id.recycler); recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 5)); adapter = new RecyclerViewAdapter(items); adapter.setOnItemClickListener(this); recyclerView.setAdapter(adapter);
那么,我该如何更新适配器数据才能显示新收到的项目呢?
更新:问题是gridView的布局看起来如下所示:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:tag="catalog_fragment" android:layout_height="match_parent"> <FrameLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler" android:layout_width="match_parent" android:layout_height="match_parent" android:clipToPadding="false"/> <ImageButton android:id="@+id/fab" android:layout_gravity="top|end" style="@style/FabStyle"/> </FrameLayout> </LinearLayout>
然后,我刚刚删除了LinearLayout
,并将FrameLayout
作为父级布局。
我正在使用RecyclerView,删除和更新都很好。
1)删除:有一个步骤从RecyclerView中删除一个项目
list.remove(position); recycler.removeViewAt(position); mAdapter.notifyItemRemoved(position); mAdapter.notifyItemRangeChanged(position, list.size());
这些代码行我工作。
2)更新数据:我唯一需要做的是
mAdapter.notifyDataSetChanged();
您必须在Actvity / Fragment代码中执行所有这些操作,而不是在RecyclerView适配器代码中。
这对我来说是有效的:
recyclerView.setAdapter(new RecyclerViewAdapter(newList)); recyclerView.invalidate();
创build一个包含更新列表的新适配器(在我的情况下,它是一个数据库转换成一个ArrayList),并设置为适配器,我试着recyclerView.invalidate()
,它的工作。
你有2个select来做到这一点:从适配器刷新UI:
mAdapter.notifyDataSetChanged();
或者从recyclerView本身刷新它:
recyclerView.invalidate();
我用不同的方式解决了同样的问题。 我没有数据,我从后台线程等待它,所以从一个emty列表开始。
mAdapter = new ModelAdapter(getContext(),new ArrayList<Model>()); // then when i get data mAdapter.update(response.getModelList()); // and update is in my adapter public void update(ArrayList<Model> modelList){ adapterModelList.clear(); for (Product model: modelList) { adapterModelList.add(model); } mAdapter.notifyDataSetChanged(); }
而已。
另一个select是使用diffutil 。 它会将原始列表与新列表进行比较,如果有更改,则使用新列表作为更新。
基本上,我们可以使用DiffUtil来比较旧数据和新数据,并以您的名义调用notifyItemRangeRemoved,notifyItemRangeChanged和notifyItemRangeInserted。
使用diffUtil代替notifyDataSetChanged的快速示例:
DiffResult diffResult = DiffUtil .calculateDiff(new MyDiffUtilCB(getItems(), items)); //any clear up on memory here and then diffResult.dispatchUpdatesTo(this);
如果它是一个大列表,我会在主线程中执行calclateDiff工作。
更新listview,gridview和recyclerview的数据
mAdapter.notifyDataSetChanged();
要么
mAdapter.notifyItemRangeChanged(0, itemList.size());
向当前数据添加新数据的最好和最酷的方法是
ArrayList<String> newItems = new ArrayList<String>(); newItems = getList(); int oldListItemscount = alcontainerDetails.size(); alcontainerDetails.addAll(newItems); recyclerview.getAdapter().notifyItemChanged(oldListItemscount+1, al_containerDetails);
我经过很长时间才得到答案
SELECTEDROW.add(dt); notifyItemInserted(position); SELECTEDROW.remove(position); notifyItemRemoved(position);
如果以上评论中没有提到任何内容为你工作。 这可能意味着问题在于别的地方。
我find解决scheme的一个地方就是我将这个列表设置到适配器上。 在我的活动中,这个列表是一个实例variables,当有任何数据改变时我直接改变它。 由于它是一个参考variables,有一些奇怪的事情。 所以我将引用variables改为本地variables,并使用另一个variables来更新数据,然后传递给上面答案中提到的addAll()
函数。
我看到所有这些需要时间的方法,我find了一个方法。
我只是包含了一个Intent本身,并叫完成 ,这确保清单刷新。
Intent intent = new Intent(context,thisActivity.class); startActivity(intent); finish();
完成!