Q: ImageView in ListItem filter is not getting filtered in Android I have a Search filter which has to filter the items based on the text input. Each list item consists of two TextViews and one ImageView. I have attached adapters and the filter is working fine with the two textviews but the corresponding ImageViews are not getting filtered (the order of images is not changing).
I tried to change the code in several ways but its not working. In here, my Adapter extends ArrayAdapter. I tried using the BaseAdapter too, but still doesn't work
My Adapter class:
import de.hdodenhof.circleimageview.CircleImageView;

public class ChefSearchResultAdapter extends ArrayAdapter<ChefSearchItem> implements Filterable {

    private ArrayList<ChefSearchItem> modelValues;
    private List<ChefSearchItem> mOriginalValues;
    private Context context;

    private static class ViewHolder {
        TextView userName;
        TextView userAdmirers;
        CircleImageView userProfileImage;
    }

    public ChefSearchResultAdapter(Context context, ArrayList<ChefSearchItem> chefs) {
        super(context, 0, chefs);
        modelValues = chefs;
        this.context=context;

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        // Get the data item for this position
        ChefSearchItem chef = getItem(position);

        // Check if an existing view is being reused, otherwise inflate the view
        final ViewHolder viewHolder; // view lookup cache stored in tag

        if (convertView == null) {
            // If there's no view to re-use, inflate a brand new view for row
            viewHolder = new ViewHolder();
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(R.layout.chef_search_listitem, parent, false);
            viewHolder.userName = convertView.findViewById(R.id.user_name);
            viewHolder.userAdmirers = convertView.findViewById(R.id.user_admirers);
            viewHolder.userProfileImage = convertView.findViewById(R.id.profile_image);

            // Cache the viewHolder object inside the fresh view
            convertView.setTag(viewHolder);
        } else {
            // View is being recycled, retrieve the viewHolder object from tag
            viewHolder = (ViewHolder) convertView.getTag();
        }
        final StorageReference storageReference = FirebaseStorage.getInstance().getReference("Users").child(chef.userUID);
        storageReference.child("Profile Pic").getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
            @Override
            public void onSuccess(Uri uri) {
                //Picasso.get().load(uri).into(viewHolder.userProfileImage);
                Picasso.get()
                    .load(uri)
                    .networkPolicy(NetworkPolicy.OFFLINE)
                    .into(viewHolder.userProfileImage, new Callback() {
                        @Override
                        public void onSuccess() {

                        }

                        @Override
                        public void onError(Exception e) {
                            Picasso.get()
                                .load(uri)
                                .into(viewHolder.userProfileImage, new Callback() {
                                    @Override
                                    public void onSuccess() {

                                    }

                                    @Override
                                    public void onError(Exception e) {
                                        Log.v("Picasso","Could not fetch image");
                                    }

                                });
                        }
                    });
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception exception) {
                // Handle any errors
            }
        });

        // Populate the data from the data object via the viewHolder object
        // into the template view.
        viewHolder.userName.setText(chef.userName);
        viewHolder.userAdmirers.setText(chef.userAdmirers);

        //Set on click to listitem
        LinearLayout listItem = convertView.findViewById(R.id.chef_listitem);
        listItem.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Navigate user to selected chef profile
                Intent i=new Intent(context,ChefsViewActivity.class);
                i.putExtra("UID",chef.userUID);
                i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(i);
            }
        });


        // Return the completed view to render on screen
        return convertView;
    }

    @Override
    public Filter getFilter() {

        Filter filter = new Filter() {

            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {

                modelValues.clear();
                modelValues.addAll((ArrayList<ChefSearchItem>) results.values);

                notifyDataSetChanged();
            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {

                FilterResults results = new FilterResults();
                // Holds the results of a filtering values

                List<ChefSearchItem> FilteredArrList = new ArrayList<>();

                if (mOriginalValues == null) {
                    mOriginalValues = new ArrayList<>(modelValues); // saves

                }

                /********
                 *
                 * If constraint(CharSequence that is received) is null returns
                 * the mOriginalValues(Original) values else does the Filtering
                 * and returns FilteredArrList(Filtered)
                 *
                 ********/
                if (constraint == null || constraint.length() == 0) {

                    // set the Original result to return
                    results.count = mOriginalValues.size();
                    results.values = mOriginalValues;
                } else {
                    Locale locale = Locale.getDefault();
                    constraint = constraint.toString().toLowerCase(locale);

                    for (int i = 0; i < mOriginalValues.size(); i++) {

                        ChefSearchItem model = mOriginalValues.get(i);

                        String data = model.userName;

                        if (data.toLowerCase(locale).contains(constraint.toString())) {
                            FilteredArrList.add(model);
                        }
                    }
                    // set the Filtered result to return
                    results.count = FilteredArrList.size();
                    results.values = FilteredArrList;
                }
                return results;
            }
        };
        return filter;
    }

}


My ViewHolder:
public class ChefSearchItem {
    public String userName;
    public String userAdmirers;
    public String userUID;

    public ChefSearchItem(String userName, String userAdmirers, String userUID) {
        this.userName = userName;
        this.userAdmirers = userAdmirers;
        this.userUID = userUID;
    }
}


A: More simpler way to filter out data is filter them locally
In your activity where your searchview is on submit call this method and pass the search string as parameter.
Make a temporary list which will consist of filterdata.
filter(String filter){
 ArrayList<ChefSearchItem> filtereModelValues = new ArrayList<ChefSearchItem>();
 for (ChefSearchItem chefSearchItem : <LIST YOU ARE SENDING TO ADAPTER>){
    if(filter.toLowerCase().equals(chechefSearchItem.userUID.toLowerCase())
       filtereModelValues.add(chefSearchItem );
 }

  //outside the for loop send the filtered list to adapter by creating method inside adapter name "filter" and pass filterList as parameter.
  YOUR_ADAPTER.filter(filtereModelValues);

} 

And in your adapter
public void filter(ArrayList<ChefSearchItem> filterModelValues){
   modelValues = filterModelValues;
   notifyDataChanged();
}

