user7466895
user7466895

Reputation: 319

Android RecyclerView.Adapter allow lists of different object types in a single adapter?

I've written a stock take app which at its core pulls data from a MySQL database using an API and creates different objects e.g Product, Order, Customer, when needed.

In my settings screen I have a button for each of these which goes to different activities where the relevant information is displayed in a RecyclerView and the user can add/edit/delete these objects.

Right now I have 3 adapters for the 3 RecyclerViews in these activities. I'm trying to create a single adapter as the functionality is almost identical.

My issue is in how to go about having one adapter that will accept e.g an ArrayList<Product> or an ArrayList<Customer>, or if that's even the best way to go about it. Just a point in the right direction would be much appreciated!

Upvotes: 1

Views: 1107

Answers (2)

Eric Marcelino
Eric Marcelino

Reputation: 1728

According to your situation, you can either:

  1. Make RecylerView that accepts multiple types of layouts which each of the layout accept one type of Object
  2. Make your ViewHolder accept all kinds of Objects and use condition to differentiate the layout/behaviour

If you choose the second option (which you already use) you must make all Class inherit one Abtract Class. For example you can create one Class called Data, then Customer, Product, and Order will extends Data Class. Then you use ArrayList<Data> in your adapter

Upvotes: 0

Chintan Soni
Chintan Soni

Reputation: 25267

You're thinking in right direction. I have already created a class that solves your problem:

public abstract class BaseRecyclerAdapter<T, VH extends BaseViewHolder> extends RecyclerView.Adapter<VH> {

    private int mModelLayout;
    private Class<VH> mViewHolderClass;
    private List<T> mList = new ArrayList<>();

    public BaseRecyclerAdapter(Class<VH> viewHolderClass, int modelLayout) {
        mModelLayout = modelLayout;
        mViewHolderClass = viewHolderClass;
    }

    public void setmList(List<T> mList) {
        this.mList = mList;
    }

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

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

    @Override
    public VH onCreateViewHolder(ViewGroup parent, int viewType) {
        ViewGroup view = (ViewGroup) LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
        try {
            Constructor<VH> constructor = mViewHolderClass.getConstructor(View.class);
            return constructor.newInstance(view);
        } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void onBindViewHolder(VH viewHolder, int position) {
        T model = getItem(position);
        populateViewHolder(viewHolder, model, position);
    }

    @Override
    public int getItemViewType(int position) {
        return mModelLayout;
    }

    abstract protected void populateViewHolder(VH viewHolder, T model, int position);

    public void addItem(T t) {
        int index = mList.size();
        mList.add(index, t);
        notifyItemInserted(index);
    }

    public void updateItem(int position, T t) {
        mList.set(position, t);
        notifyItemChanged(position);
    }

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

    public void setItems(List<T> items) {
        mList = items;
        notifyDataSetChanged();
    }

    public class BaseViewHolder extends RecyclerView.ViewHolder {
        public BaseViewHolder(View view) {
            super(view);
        }
    }
}

How to use it:

private BaseRecyclerAdapter<User, UserViewHolder> mBaseRecyclerAdapter = new BaseRecyclerAdapter<User, UserViewHolder>(UserViewHolder.class, R.layout.layout_list_item_friends) {
    @Override
    protected void populateViewHolder(UserViewHolder viewHolder, User model, int position) {
        // You can do here whatever you want
    }
};

Upvotes: 1

Related Questions