J'ai un RecyclerView qui affiche des données extraites de la base de données de la salle à l'aide de MVVM. J'ai aussi un ediitext que j'utilise pour rechercher ou filtrer les éléments recyclerview. Le problème est que lorsque j'appuie sur l'élément recyclerview (met à jour une valeur dans la base de données), puis que je le filtre, il filtre mais duplique ensuite toutes les données. Voici le code : Code complet de l'adaptateur :

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

Et voici le code de filtrage edittext de mon activité :

attendee_search.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
        attendeesAdapter.getFilter().filter(s.toString());
        }

@Override
public void afterTextChanged(Editable s) { }});

Voici la capture d'écran avant de cliquer sur l'élément :

enter image description here

Et après avoir cliqué et filtré : entrez la description de l'image ici

0
Whiteq 3 févr. 2020 à 16:02

1 réponse

Meilleure réponse

Pour moi, c'est la meilleure approche pour travailler avec 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();
}

}

Avec cela, vous pouvez vous assurer que vous n'aurez pas d'éléments en double.

1
omensight 3 févr. 2020 à 14:07