5
\$\begingroup\$

I have tried to create a GenericAdapter that can help you search, sort automatically without writing a lot of code.

But in order to use this you have to follow some rules. How can I make it better and where am I not using a better approach.

rules for using GenericAdapter.

  1. extends your business model with BaseModel
  2. extends your viewHolder with BaseViewHolder
  3. your adapter must extends GenericAdapter

where

BaseModel.class

public abstract class BaseModel<T> implements Comparator<T>
{
   public abstract String getAttributeToSearch();
   ///public abstract int whatYouWantToCompare();
}

BaseViewHolder.class

public abstract class BaseViewHolder<T extends BaseModel> extends RecyclerView.ViewHolder 
{

  public BaseViewHolder(View itemView) {
    super(itemView);
  }

  public abstract void bindData(T data);
}

GenericBaseAdapter.class

public abstract class GenericBaseAdapter<T extends BaseModel, U extends BaseViewHolder> extends RecyclerView.Adapter<U> implements Filterable {

    private Context mContext;
    private List<T> itemList;
    private List<T> origList;

    public GenericBaseAdapter(Context mContext, List<T> itemList) {
        this.mContext = mContext;
        this.itemList = itemList;
        this.origList = itemList;
    }

    @Override
    public void onBindViewHolder(U holder, int position) {
        holder.bindData(itemList.get(position));
    }

    @Override
    public int getItemCount() {
        return itemList.size();
    }

    public T getItem(int position) {
        return itemList.get(position);
    }

    public void setItems(List<T> itemList) {
        this.itemList = itemList;
        this.origList = itemList;
        notifyDataSetChanged();
    }

    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                final FilterResults oReturn = new FilterResults();
                final ArrayList<T> results = new ArrayList<>();
                if (origList == null)
                    origList = new ArrayList<>(itemList);
                if (constraint != null && constraint.length() > 0) {
                    if (origList != null && origList.size() > 0) {
                        for (final T cd : origList) {
                            if (cd.getAttributeToSearch().toLowerCase()
                                    .contains(constraint.toString().toLowerCase()))
                                results.add(cd);
                        }
                    }
                    oReturn.values = results;
                    oReturn.count = results.size();//newly Aded by ZA
                } else {
                    oReturn.values = origList;
                    oReturn.count = origList.size();//newly added by ZA
                }
                return oReturn;
            }

            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(final CharSequence constraint,
                                          FilterResults results) {
                itemList = new ArrayList<>((ArrayList<T>) results.values);
                // FIXME: 8/16/2017 implement Comparable with sort below
                ///Collections.sort(itemList);
                notifyDataSetChanged();
            }
        };
    }

    public void sortItems(T obje) {
        Collections.sort(itemList, obje);
        notifyDataSetChanged();
    }
}

for sorting use

mAdapter.sortItems(productList.get(0));

for searching..

mAdapter.getFilter().filter("any string to search");
\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

Here are some suggestions take what you like from it:

  • You can make BaseModel an interface. This gives the added benefit that your models do not need to extend your abstract class.

  • In your getFilter method in a code review I'd ask you to put curly braces around your first if.

    if (origList == null) { origList = new ArrayList<>(itemList); }

  • You can instantiate your filter once as a member of the class, rather than instantiating a new one every time the function getFilter is called.

  • Use collections.unmodifiablelist to protect yourself from unwanted mutations of the original list, when creating or assigning a new list. This is just a precautionary suggestion that has performance implications. Your not mutating when you should not be.

\$\endgroup\$
5
  • \$\begingroup\$ After converting my BaseModel to interface . My adapter should be like T implements BaseModel . Am I right \$\endgroup\$ Sep 12, 2017 at 5:23
  • \$\begingroup\$ No, still just extends keyword in that case. \$\endgroup\$ Sep 12, 2017 at 5:26
  • \$\begingroup\$ and in getFilter you are talking about new Filter() or the list (origList ) I created each time \$\endgroup\$ Sep 12, 2017 at 5:33
  • \$\begingroup\$ new Filter() \$\endgroup\$ Sep 12, 2017 at 15:45
  • \$\begingroup\$ you should try this github.com/manojbhadane/GenericAdapter \$\endgroup\$ May 29, 2019 at 10:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.