Blankj/AndroidUtilCode · error · RuntimeException

onCreateViewHolder: get holder from view type failed.

Error message

onCreateViewHolder: get holder from view type failed.

What it means

BaseItem.onCreateViewHolder throws RuntimeException when the RecyclerView requests a viewType that is present in neither the static LAYOUT_SPARSE_ARRAY nor the VIEW_SPARSE_ARRAY. Each BaseItem registers its viewType (derived from layoutId/view + class hashCode) in its constructor, so this throw means the adapter returned a viewType that no item ever registered.

Source

Thrown at lib/base/src/main/java/com/blankj/base/rv/BaseItem.java:38

 *     desc  :
 * </pre>
 */
public abstract class BaseItem<T extends BaseItem> {

    private static final SparseIntArray    LAYOUT_SPARSE_ARRAY = new SparseIntArray();
    private static final SparseArray<View> VIEW_SPARSE_ARRAY   = new SparseArray<>();
    public boolean isBindViewHolder = false;

    static ItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        int layoutByType = LAYOUT_SPARSE_ARRAY.get(viewType, -1);
        if (layoutByType != -1) {
            return new ItemViewHolder(LayoutInflater.from(parent.getContext()).inflate(layoutByType, parent, false));
        }
        View viewByType = VIEW_SPARSE_ARRAY.get(viewType);
        if (viewByType != null) {
            return new ItemViewHolder(viewByType);
        }
        throw new RuntimeException("onCreateViewHolder: get holder from view type failed.");
    }

    public abstract void bind(@NonNull final ItemViewHolder holder, final int position);

    public void partialUpdate(List<Object> payloads) {
    }

    void bindViewHolder(@NonNull final ItemViewHolder holder, final int position) {
        isBindViewHolder = true;
        if (mOnItemClickListener != null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mOnItemClickListener != null) {
                        //noinspection unchecked
                        mOnItemClickListener.onItemClick(holder, (T) BaseItem.this, getIndex());
                    }
                }

View on GitHub (pinned to 7b4caf9e54)

Solutions

  1. Do not override BaseItem.getViewType(); let the constructor register layout/view against viewType in the SparseArrays.
  2. Ensure every distinct item type is constructed via new BaseItem(layoutId) or new BaseItem(view) so its viewType is registered before the adapter binds.
  3. If you must customise the viewType, also put the corresponding layout/view into LAYOUT_SPARSE_ARRAY/VIEW_SPARSE_ARRAY under that same int.

Example fix

// before: viewType no longer matches the stored layout
@Override public int getViewType() { return 9999; } // not in LAYOUT_SPARSE_ARRAY -> throw

// after
// remove the override; viewType is auto-derived and registered in the constructor
Defensive patterns

Strategy: validation

Validate before calling

// Ensure each item registers its viewType via its constructor; do not override getViewType().
// Verify the adapter feeds only registered viewTypes:
int vt = item.getViewType();
// BaseItem registers vt -> layout in its constructor, so just construct items normally.

Try / catch

try {
    // adapter operations
} catch (RuntimeException e) {
    if (e.getMessage().contains("get holder from view type")) {
        // a viewType was not registered; audit item getViewType overrides
    }
}

Prevention

When it happens

Trigger: getItemViewType on the adapter/Item returns an int that does not match any BaseItem's getViewType(); mixing items whose viewType registration was lost (e.g., static arrays cleared or a process restart losing the SparseArrays); subclassing BaseItem and overriding getViewType to a custom value without populating the arrays.

Common situations: Overriding getViewType() to return a different value than the constructor stored; reusing a stale viewType integer after items were recreated; a custom adapter feeding an unknown viewType into this static onCreateViewHolder.

Related errors


AI-assisted analysis of Blankj/AndroidUtilCode@7b4caf9e54 (2026-08-14). Data as JSON: /api/errors/cf62ba5591fa2660. Report an issue: GitHub.