Sometimes a RecyclerView will need to use several types of Views to be displayed in the list shown in the UI, and each View needs a different layout xml to be inflated.

For this issue, you may use different ViewHolders in single Adapter, by using a special method in RecyclerView - getItemViewType(int position).

Below is example of using two ViewHolders:

  1. A ViewHolder for displaying list entries
  2. A ViewHolder for displaying multiple header views
@Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(context).inflate(viewType, parent, false);
        return ViewHolder.create(itemView, viewType);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        final Item model = this.items.get(position);
        ((ViewHolder) holder).bind(model);
    }

    @Override
    public int getItemViewType(int position) {
        return inSearchState ? R.layout.item_header : R.layout.item_entry;
    }

    abstract class ViewHolder {
        abstract void bind(Item model);

        public static ViewHolder create(View v, int viewType) {
            return viewType == R.layout.item_header ? new HeaderViewHolder(v) :new EntryViewHolder(v);
        }
    }  
    
    static class EntryViewHolder extends ViewHolder {
        private View v;

        public EntryViewHolder(View v) {
            this.v = v;
        }

        @Override public void bind(Item model) {
            // Bind item data to entry view.
        }
    }
    
    static class HeaderViewHolder extends ViewHolder {
        private View v;

        public HeaderViewHolder(View v) {
            this.v = v;
        }

        @Override public void bind(Item model) {
            // Bind item data to header view.
        }
    }