package com.kennyc.adapters;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by kcampagna on 5/29/15.
 */
public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    protected final String TAG = getClass().getSimpleName();

    private List<T> mItems;

    protected LayoutInflater mInflater;

    /**
     * Simple constructor for creating a BaseRecyclerAdapter
     *
     * @param context    The context the adapter is running in
     * @param collection A list of items to populate the adapter with, can be null. If passing a null list,
     *                   {@link #addItem(Object)} will throw an exception as the list type is undefined. The list
     *                   needs to be created first with {@link #addItems(List)}
     */
    public BaseRecyclerAdapter(Context context, List<T> collection) {
        mItems = collection;
        mInflater = LayoutInflater.from(context);
    }

    /**
     * Adds an item to the list, {@link #notifyDataSetChanged()} will be called
     *
     * @param object Object to add to the adapter
     */
    public void addItem(T object) {
        // An exception is thrown instead of creating a List object since the type of list in unknown
        if (mItems == null) throw new NullPointerException("Adapter list has not been initialized");
        mItems.add(object);
        notifyDataSetChanged();
    }

    /**
     * Adds a list of items to the adapter list, {@link #notifyDataSetChanged()} will be called
     *
     * @param items List of items to add to the adapter
     */
    public void addItems(List<T> items) {
        if (items == null || items.isEmpty()) {
            return;
        }

        if (mItems == null) {
            mItems = items;
        } else {
            mItems.addAll(items);
        }

        notifyDataSetChanged();
    }

    /**
     * Removes an object from the list
     *
     * @param object The object to remove from the adapter
     * @return If the object was removed
     */
    public boolean removeItem(T object) {
        if (mItems != null) {
            boolean removed = mItems.remove(object);
            notifyDataSetChanged();
            return removed;
        }

        return false;
    }

    /**
     * Removes an item at the given position, {@link #notifyDataSetChanged()} will be called
     *
     * @param position The position to remove from the adapter
     * @return The item removed
     */
    public T removeItem(int position) {
        if (mItems != null) {
            T removedItem = mItems.remove(position);
            notifyDataSetChanged();
            return removedItem;
        }

        return null;
    }

    /**
     * Removes all items from the list, {@link #notifyDataSetChanged()} will be called
     */
    public void clear() {
        if (mItems != null) {
            mItems.clear();
            notifyDataSetChanged();
        }
    }

    /**
     * Returns the entire list. This is <b><i>not</i></b> a copy of the list. If a copy of the list is
     * needed, see {@link #retainItems()}
     *
     * @return The entire list of items in the adapter
     */
    protected List<T> getAllItems() {
        return mItems;
    }

    /**
     * Returns the object for the given position
     *
     * @param position The position to return
     * @return The item at the given position
     */
    public T getItem(int position) {
        return mItems.get(position);
    }

    /**
     * Returns an ArrayList of the items in the adapter, used for saving the items for configuration changes
     *
     * @return A copy of the items in the adapter
     */
    public ArrayList<T> retainItems() {
        return new ArrayList<>(mItems);
    }

    @Override
    public int getItemCount() {
        return mItems != null ? mItems.size() : 0;
    }

    /**
     * Returns if the adapter is empty
     *
     * @return If the adapter is empty
     */
    public boolean isEmpty() {
        return mItems == null || mItems.size() <= 0;
    }
}

@@ -1504,39 +1504,50 @@
       notify
-DataSetChanged(
+ItemInserted(mItems.size()
 );%0A    %7D%0A%0A  
@@ -1832,32 +1832,88 @@
 urn;%0A        %7D%0A%0A
+        int startingSize = 0;%0A        int endSize = 0;%0A%0A
         if (mIte
@@ -1971,16 +1971,58 @@
  else %7B%0A
+            startingSize = mItems.size();%0A
         
@@ -2066,37 +2066,94 @@
         
-notifyDataSetChanged(
+endSize = mItems.size();%0A        notifyItemRangeInserted(startingSize, endSize
 );%0A    %7D
@@ -2404,23 +2404,20 @@
     
-boolean removed
+int position
  = m
@@ -2422,22 +2422,23 @@
  mItems.
-remove
+indexOf
 (object)
@@ -2455,58 +2455,60 @@
     
-notifyDataSetChanged();%0A            return removed
+return position %3E= 0 && removeItem(position) != null
 ;%0A  
@@ -2893,39 +2893,44 @@
       notify
-DataSetChanged(
+ItemRemoved(position
 );%0A         
@@ -3142,32 +3142,70 @@
 tems != null) %7B%0A
+            int size = mItems.size();%0A
             mIte
@@ -3234,31 +3234,40 @@
   notify
-DataSetChanged(
+ItemRangeRemoved(0, size
 );%0A     

Allow RecyclerView Animations