Android 在筛选recyclerview时,项目被复制
我有一个RecyclerView,它显示了使用MVVM从房间db获取的数据。此外,我还有一个用于搜索或筛选recyclerview项目的ediitext。问题是当我按下recyclerview项(更新数据库中的一些值)然后过滤它时,它会过滤但会复制所有数据。 代码如下: 完整的适配器代码:Android 在筛选recyclerview时,项目被复制,android,mvvm,android-recyclerview,filtering,android-livedata,Android,Mvvm,Android Recyclerview,Filtering,Android Livedata,我有一个RecyclerView,它显示了使用MVVM从房间db获取的数据。此外,我还有一个用于搜索或筛选recyclerview项目的ediitext。问题是当我按下recyclerview项(更新数据库中的一些值)然后过滤它时,它会过滤但会复制所有数据。 代码如下: 完整的适配器代码: private Context mCtx; private List<AttendeesTable> itemList = new ArrayList<>(); private Lis
private Context mCtx;
private List<AttendeesTable> itemList = new ArrayList<>();
private List<AttendeesTable> filterItemList = new ArrayList<>();
private EventsViewModel eventsViewModel;
long DURATION = 500;
private boolean on_attach = true;
public AttendeesAdapter() {
}
@NonNull
@Override
public EventsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_attendance, parent, false);
return new EventsViewHolder(view, mCtx, viewType);
}
@Override
public void onBindViewHolder(@NonNull final EventsViewHolder holder, final int position) {
final int is_arrived = itemList.get(position).getHas_arrived();
if (is_arrived == 1){
holder.attendee_arrived_not.setVisibility(View.INVISIBLE);
holder.attendee_arrived.setVisibility(View.VISIBLE);
holder.attendee_view.setCardBackgroundColor(Color.parseColor("#dcffda"));
}else if (is_arrived ==0){
holder.attendee_arrived_not.setVisibility(View.VISIBLE);
holder.attendee_arrived.setVisibility(View.INVISIBLE);
holder.attendee_view.setCardBackgroundColor(Color.WHITE);
}
setAnimation(holder.itemView,position);
holder.attendeeSeatNumber.setText(itemList.get(position).getSeat_no());
holder.attendeeTicketNo.setText(itemList.get(position).getTicket_no());
holder.mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
String currentDateandTime = sdf.format(new Date());
if (is_arrived == 0){
eventsViewModel.updateAttendees(1,currentDateandTime, itemList.get(position).getQr_code_id());
holder.attendee_arrived_not.setVisibility(View.INVISIBLE);
holder.attendee_arrived.setVisibility(View.VISIBLE);
notifyItemRemoved(position);
holder.attendee_view.setCardBackgroundColor(Color.parseColor("#dcffda"))z
}else if (is_arrived ==1){
eventsViewModel.updateAttendees(0,"no_time", itemList.get(position).getQr_code_id());
holder.attendee_arrived_not.setVisibility(View.VISIBLE);
holder.attendee_arrived.setVisibility(View.INVISIBLE);
holder.attendee_view.setCardBackgroundColor(Color.WHITE);
notifyItemRemoved(position);
}
}
});
}
@Override
public int getItemCount() {
return itemList.size();
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
constraint = constraint.toString().toLowerCase().trim();
itemList.clear();
if (constraint.length() == 0) {
itemList.addAll(filterItemList);
} else {
for (AttendeesTable item : filterItemList) {
String name = item.getFirst_name() + " " + item.getLast_name();
if (item.getTicket_no().toLowerCase(Locale.getDefault()).contains(constraint) ||
item.getEmail().toLowerCase(Locale.getDefault()).contains(constraint) ||
name.toLowerCase(Locale.getDefault()).contains(constraint) ||
item.getSeat_no().toLowerCase(Locale.getDefault()).contains(constraint)){
itemList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = itemList;
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
notifyDataSetChanged();
}
};
}
public class EventsViewHolder extends RecyclerView.ViewHolder {
TextView attendeeName, attendeeEmail, attendeeSeatNumber, attendeeTicketNo;
ImageView attendee_arrived, attendee_arrived_not;
CardView attendee_view;
public Context context;
View mView;
public EventsViewHolder(View itemView, Context context, int viewType) {
super(itemView);
mView = itemView;
this.context = context;
attendeeEmail = itemView.findViewById(R.id.attendee_email);
attendeeName = itemView.findViewById(R.id.attendee_name);
attendeeSeatNumber = itemView.findViewById(R.id.attendee_seat_number);
attendee_arrived = itemView.findViewById(R.id.attendee_arrived);
attendee_arrived_not = itemView.findViewById(R.id.attendee_arrived_x);
attendee_view = itemView.findViewById(R.id.attendee_view);
attendeeTicketNo = itemView.findViewById(R.id.attendee_ticket_no);
}
}
public void setAttendees(List<AttendeesTable> events, Context mCtx, EventsViewModel eventsViewModel) {
this.itemList = events;
this.mCtx = mCtx;
this.eventsViewModel = eventsViewModel;
filterItemList.addAll(events);
notifyDataSetChanged();
}
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
Log.d(TAG, "onScrollStateChanged: Called " + newState);
on_attach = false;
super.onScrollStateChanged(recyclerView, newState);
}
});
super.onAttachedToRecyclerView(recyclerView);
}
private void setAnimation(View itemView, int i) {
if(!on_attach){
i = -1;
}
boolean isNotFirstItem = i == -1;
i++;
itemView.setAlpha(0.f);
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator animator = ObjectAnimator.ofFloat(itemView, "alpha", 0.f, 0.5f, 1.0f);
ObjectAnimator.ofFloat(itemView, "alpha", 0.f).start();
animator.setStartDelay(isNotFirstItem ? DURATION / 2 : (i * DURATION / 3));
animator.setDuration(500);
animatorSet.play(animator);
animator.start();
}
以下是单击项目前的屏幕截图:
单击并过滤后:
对我来说,这是使用MVVM的更好方法
public class DiffExampleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<AttendeesTable> items;
private List<AttendeesTable> filteredItems = new ArrayList<>();
private String filter = "";
//Call this method each time your data change
public void setItems(List<AttendeesTable> newItems){
items = newItems;
filteredItems.clear();
filteredItems.addAll(items);
calcDiff();
}
//Call this method for filter items with the string of your editText
//Don't forget to call trim() in the string before to call this method to avoid a malformed filter
public void filterItems(String externalFilter){
this.filter = externalFilter;
filteredItems.clear();
for (AttendeesTable attendeesTable:
items) {
//Add all your constraints here
if (attendeesTable.getId().contains(filter)){
filteredItems.add(attendeesTable);
}
calcDiff();
}
}
//This diffUtil calculates the changes automatically
private void calcDiff(){
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtil.Callback() {
@Override
public int getOldListSize() {
return items.size();
}
@Override
public int getNewListSize() {
return filteredItems.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
//Just check the ID
String oldIdAtPosition = items.get(oldItemPosition).getId();
String newIdAtPosition = filteredItems.get(newItemPosition).getId();
return oldIdAtPosition.equals(newIdAtPosition);
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
// You can add more conditions here for check if the items are the same,
// but in this case is enough to checking the ids of each item, unless
// you have state changes like item selected or name of the item changed
String oldIdAtPosition = items.get(oldItemPosition).getId();
String newIdAtPosition = filteredItems.get(newItemPosition).getId();
return oldIdAtPosition.equals(newIdAtPosition);
}
});
diffResult.dispatchUpdatesTo(this);
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//Return your ViewHolder Here
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
//Play with your viewHolder here
}
@Override
public int getItemCount() {
//return your filteredItems size
return filteredItems.size();
}
公共类differexampleAdapter扩展了RecyclerView.Adapter{
私人清单项目;
private List filteredItems=new ArrayList();
私有字符串过滤器=”;
//每次数据更改时调用此方法
公共无效集合项(列出新项){
项目=新项目;
filteredItems.clear();
filteredItems.addAll(项目);
calcDiff();
}
//为具有editText字符串的筛选器项调用此方法
//在调用此方法之前,不要忘记在字符串中调用trim(),以避免出现格式错误的筛选器
公共无效筛选器项(字符串外部筛选器){
this.filter=externalFilter;
filteredItems.clear();
对于(AttendeStable AttendeStable:
(项目){
//在此处添加所有约束
if(attendestable.getId().contains(filter)){
filteredItems.add(attendestable);
}
calcDiff();
}
}
//此diffUtil自动计算更改
私有void calcDiff(){
DiffUtil.diffesult diffesult=DiffUtil.calculateDiff(新的DiffUtil.Callback(){
@凌驾
public int getOldListSize(){
返回items.size();
}
@凌驾
public int getNewListSize(){
返回filteredItems.size();
}
@凌驾
公共布尔值areItemsTheSame(int-oldItemPosition,int-newItemPosition){
//检查一下身份证就行了
字符串oldIdAtPosition=items.get(oldItemPosition.getId();
字符串newIdAtPosition=filteredItems.get(newItemPosition.getId();
返回oldIdAtPosition.equals(newIdAtPosition);
}
@凌驾
公共布尔值是相同的内容(int oldItemPosition,int newItemPosition){
//您可以在此处添加更多条件以检查项目是否相同,
//但在这种情况下,检查每个项目的ID就足够了,除非
//您的状态发生了更改,如“已选择项目”或“已更改项目名称”
字符串oldIdAtPosition=items.get(oldItemPosition.getId();
字符串newIdAtPosition=filteredItems.get(newItemPosition.getId();
返回oldIdAtPosition.equals(newIdAtPosition);
}
});
diffResult.dispatchUpdatesTo(本);
}
@非空
@凌驾
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup父级,int-viewType){
//在这里归还您的取景器
}
@凌驾
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder,int位置){
//在这里玩你的取景器
}
@凌驾
public int getItemCount(){
//返回您的filteredItems大小
返回filteredItems.size();
}
}
这样,您可以确保不会有重复的项。您使用的是DiffUtil吗?添加完整的适配器code@Md.Asaduzzaman,添加了完整的适配器code@MijaelViricochea不,我不用它。我需要用它吗?如果是,为什么?@MijaelViricochea,我现在读到了。如果我是对的,它用于用新列表更新上一个列表。我尝试了这段代码,但不幸的是,筛选的项目没有更新shown@White是否在筛选之前调用setItems()方法?是的,它会获取所有数据,但当我开始筛选时,所有数据都会消失
public class DiffExampleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<AttendeesTable> items;
private List<AttendeesTable> filteredItems = new ArrayList<>();
private String filter = "";
//Call this method each time your data change
public void setItems(List<AttendeesTable> newItems){
items = newItems;
filteredItems.clear();
filteredItems.addAll(items);
calcDiff();
}
//Call this method for filter items with the string of your editText
//Don't forget to call trim() in the string before to call this method to avoid a malformed filter
public void filterItems(String externalFilter){
this.filter = externalFilter;
filteredItems.clear();
for (AttendeesTable attendeesTable:
items) {
//Add all your constraints here
if (attendeesTable.getId().contains(filter)){
filteredItems.add(attendeesTable);
}
calcDiff();
}
}
//This diffUtil calculates the changes automatically
private void calcDiff(){
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtil.Callback() {
@Override
public int getOldListSize() {
return items.size();
}
@Override
public int getNewListSize() {
return filteredItems.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
//Just check the ID
String oldIdAtPosition = items.get(oldItemPosition).getId();
String newIdAtPosition = filteredItems.get(newItemPosition).getId();
return oldIdAtPosition.equals(newIdAtPosition);
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
// You can add more conditions here for check if the items are the same,
// but in this case is enough to checking the ids of each item, unless
// you have state changes like item selected or name of the item changed
String oldIdAtPosition = items.get(oldItemPosition).getId();
String newIdAtPosition = filteredItems.get(newItemPosition).getId();
return oldIdAtPosition.equals(newIdAtPosition);
}
});
diffResult.dispatchUpdatesTo(this);
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//Return your ViewHolder Here
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
//Play with your viewHolder here
}
@Override
public int getItemCount() {
//return your filteredItems size
return filteredItems.size();
}