How to implement getfilter() with custom adapter that extends baseadapter

A Filter has two major components, the performFiltering(CharSequence) method and the publishResults(CharSequence, FilterResults) method. In your PromotionListAdapter, you’ll need to implement the Filterable interface then Override the getFilter() method to return a new Filter that has these methods implemented.

The performFiltering(CharSequence) method is where you’ll do the bulk of your work. The CharSequence argument is the data which you’re filtering on. Here, you’ll first want to determine if the list should even be filtered as the base case. Once you’ve decided to perform the filtering, create a new ArrayList for your filtered dataset (in your case, a new ArrayList>), and loop through your complete set of list items, adding the values that match the filter to your new ArrayList.

The return type for the performFiltering method is FilterResults. FilterResults is a simple object with two variables, int count and Object results. Once performFiltering has created the new ArrayList with the filtered data, create a new FilterResults, setting your new ArrayList as results and the size of that ArrayList as count.

The publishResults(CharSequence, FilterResults) method is called after performFiltering() returns. The CharSequence parameter is the same String you were filtering on. The FilterResults parameter is the return from performFiltering(). In this method, you’ll want to set your new ArrayList as the data source for your List and then call notifyDataSetChanged() to update the UI.

In order to implement this, I’ve had success when my Adapter keeps track of both the original ArrayList of data and a filtered ArrayList of what is currently being shown. Here’s some boilerplate code based on your adapter that can help get you started. I’ve commented above important lines.

public class PromotionListAdapter extends BaseAdapter implements Filterable
{
    private Activity activity;
    private static LayoutInflater inflater = null;
    public ImageLoader imageLoader;

    //Two data sources, the original data and filtered data
    private ArrayList<HashMap<String, String>> originalData;
    private ArrayList<HashMap<String, String>> filteredData;

    public PromotionListAdapter(Activity a, ArrayList<HashMap<String, String>> d) 
    {
        activity = a;
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        imageLoader = new ImageLoader(activity.getApplicationContext());

        //To start, set both data sources to the incoming data
        originalData = d;
        filteredData = d;
    }

    //For this helper method, return based on filteredData
    public int getCount() 
    {
        return filteredData.size();
    }

    //This should return a data object, not an int
    public Object getItem(int position) 
    {
        return filteredData.get(position);
    }

    public long getItemId(int position) 
    {
        return position;
    }

    //The only change here is that we'll use filteredData.get(position)
    //Even better would be to use getItem(position), which uses the helper method (see the getItem() method above)
    public View getView(int position, View convertView, ViewGroup parent) 
    {

       View vi = convertView;
       if (convertView == null)vi = inflater.inflate(R.layout.item_list_promotion, null);

      TextView PromoID = (TextView) vi.findViewById(R.id.PromoID);
      TextView PromoName = (TextView) vi.findViewById(R.id.PromoName);
      TextView PromoImage = (TextView) vi.findViewById(R.id.PromoImage);
      TextView PromoDesc = (TextView) vi.findViewById(R.id.PromoDesc);
      TextView PromoCate = (TextView) vi.findViewById(R.id.PromoCate);
      TextView PromoContact = (TextView) vi.findViewById(R.id.PromoContact);
      TextView PromoDateStart = (TextView) vi.findViewById(R.id.PromoDateStart);
      TextView PromoDateEnd = (TextView) vi.findViewById(R.id.PromoDateEnd);
      ImageView thumb_image = (ImageView) vi.findViewById(R.id.image_promo);

      HashMap<String, String> daftar_promotion = new HashMap<String, String>();

      //Get data from filtered Data
      //This line can be replaced with:
      //     daftar_promotion = getItem(position);
      daftar_promotion = filteredData.get(position);

      PromoID.setText(daftar_promotion.get(Curve.TAG_ID_PROMO));

      PromoName.setText(daftar_promotion.get(Curve.TAG_NAMA_PROMO));

      PromoImage.setText(daftar_promotion.get(Curve.TAG_LINK_IMAGE_PROMO));

      PromoDesc.setText(daftar_promotion.get(Curve.TAG_DESC_PROMO));

      PromoCate.setText(daftar_promotion.get(Curve.TAG_CATE_PROMO));

      PromoContact.setText(daftar_promotion.get(Curve.TAG_CONT_PROMO));

      PromoDateStart.setText(daftar_promotion.get(Curve.TAG_DATES_PROMO));

      PromoDateEnd.setText(daftar_promotion.get(Curve.TAG_DATEE_PROMO));

      imageLoader.DisplayImage(daftar_promotion.get(Curve.TAG_LINK_IMAGE_PROMO),thumb_image);

      return vi;

    }

    @Override
    public Filter getFilter()
    {
       return new Filter()
       {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence)
            {
                FilterResults results = new FilterResults();

                //If there's nothing to filter on, return the original data for your list
                if(charSequence == null || charSequence.length() == 0)
                {
                    results.values = originalData;
                    results.count = originalData.size();
                }
                else
                {
                    ArrayList<HashMap<String,String>> filterResultsData = new ArrayList<HashMap<String,String>>();

                    for(HashMap<String,String> data : originalData)
                    {
                        //In this loop, you'll filter through originalData and compare each item to charSequence.
                        //If you find a match, add it to your new ArrayList
                        //I'm not sure how you're going to do comparison, so you'll need to fill out this conditional
                        if(data matches your filter criteria)
                        {
                            filterResultsData.add(data);
                        }
                    }            

                    results.values = filterResultsData;
                    results.count = filteredResultsData.size();
                }

                return results;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults filterResults)
            {
                filteredData = (ArrayList<HashMap<String,String>>)filterResults.values;
                notifyDataSetChanged();
            }
        };
    }
}

And there you have it! As far as I can tell, you’ve already implemented the TextWatcher for your inputText EditText set up properly, so adding the getFilter() method and making a few other minor changes to your Adapter should lead you to a solution. I believe you can also create a member variable on your Adapter for your Filter, so you’re not creating a new instance of the class each time getFilter() is called, but I copy/pasted this from a previous project of mine and am sure it works this way. Play with it and see what works for you! Hope this helps! And please do comment if you need anything clarified.

Leave a Comment