@Override
    public int getItemViewType(int adapterPosition) {
        if (sections == null) {
            buildSectionIndex();
        }

        if (adapterPosition < 0) {
            throw new IndexOutOfBoundsException("adapterPosition (" + adapterPosition + ") cannot be < 0");
        } else if (adapterPosition >= getItemCount()) {
            throw new IndexOutOfBoundsException("adapterPosition (" + adapterPosition + ")  cannot be > getItemCount() (" + getItemCount() + ")");
        }

        int sectionIndex = getSectionForAdapterPosition(adapterPosition);
        Section section = this.sections.get(sectionIndex);
        int localPosition = adapterPosition - section.adapterPosition;

        int baseType = getItemViewBaseType(section, localPosition);
        int userType = 0;


        switch (baseType) {
            case TYPE_HEADER:
                userType = getSectionHeaderUserType(sectionIndex);
                if (userType < 0 || userType > 0xFF) {
                    throw new IllegalArgumentException("Custom header view type (" + userType + ") must be in range [0,255]");
                }
                break;
            case TYPE_ITEM:
                // adjust local position to accommodate header & ghost header
                if (section.hasHeader) {
                    localPosition -= 2;
                }
                userType = getSectionItemUserType(sectionIndex, localPosition);
                if (userType < 0 || userType > 0xFF) {
                    throw new IllegalArgumentException("Custom item view type (" + userType + ") must be in range [0,255]");
                }
                break;
            case TYPE_FOOTER:
                userType = getSectionFooterUserType(sectionIndex);
                if (userType < 0 || userType > 0xFF) {
                    throw new IllegalArgumentException("Custom footer view type (" + userType + ") must be in range [0,255]");
                }
                break;
        }


        // base is bottom 8 bits, user type next 8 bits
        return ((userType & 0xFF) << 8) | (baseType & 0xFF);
    }
Post an action to be run later.
RecyclerView doesn't like being mutated during a scroll. We can't detect when a
scroll is actually happening, unfortunately, so the best we can do is post actions
from notify* methods to be run at a later date.

@param action action to run
android/modules/module_common/src/main/java/github/tornaco/android/thanos/widget/section/SectioningAdapter.java