Generic adapter for RecyclerView

The recently introduced RecyclerView, a successor to ListView, comes with a few handy methods to animate list changes. It’s a good opportunity to write a generic base adapter that will wrap CRUD operations and automatically trigger basic animations. Here you go:

public abstract class BaseRecyclerViewAdapter<T, Z extends RecyclerView.ViewHolder>
        extends RecyclerView.Adapter<Z> {

    protected final Context mContext;

    protected List<T> mItems;

    public BaseRecyclerViewAdapter(List<T> items, Context context) {
        if (items == null) {
            items = new ArrayList<T>();
        }
        mItems = items;
        mContext = context;
    }

    public void add(T item, int position) {
        if (item == null) {
            return;
        }
        mItems.add(position, item);
        notifyItemInserted(position);
    }

    public void add(List<T> items, int position) {
        if (items == null || items.isEmpty()) {
            return;
        }
        mItems.addAll(position, items);
        notifyItemRangeInserted(position, items.size());
    }

    public void add(T item) {
        int position = mItems.size();
        mItems.add(position, item);
        notifyItemInserted(position);
    }

    public void add(List<T> items) {
        if (items.isEmpty()) {
            return;
        }
        int position = mItems.isEmpty() ? 0 : mItems.size();
        mItems.addAll(position, items);
        notifyItemRangeInserted(position, items.size());
    }

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

    public List<T> getItems() {
        return mItems;
    }

    public int getItemCount() {
        return mItems.size();
    }

    /**
     * Requires equals() and hashcode() to be implemented in T class.
     */
    public void remove(T item) {
        int position = mItems.indexOf(item);
        if (position == -1) {
            return;
        }
        mItems.remove(position);
        notifyItemRemoved(position);
    }

    public void remove(int position) {
        mItems.remove(position);
        notifyItemRemoved(position);
    }

    public void remove(int position, int itemCount) {
        for (int i = position; i < itemCount; i++) {
            mItems.remove(i);
        }
        notifyItemRangeRemoved(position, itemCount);
    }

    public void replaceList(List<T> items) {
        mItems = items;
        notifyDataSetChanged();
    }

    public void clear() {
        mItems.clear();
        notifyDataSetChanged();
    }

T is the type of your items, and Z is a subclass of RecyclerView.ViewHolder. I usually create an abstract base class for view holders as well just so I don’t have to repeat ButterKnife bindings:

public abstract class BaseViewHolder extends RecyclerView.ViewHolder {
    public BaseViewHolder(View itemView) {
        super(itemView);
        ButterKnife.bind(this, itemView);
    }
}