Skip to content

Instantly share code, notes, and snippets.

@Anrimian
Created June 29, 2018 08:38
Show Gist options
  • Save Anrimian/fafd22d1466767d540fea21e871daa05 to your computer and use it in GitHub Desktop.
Save Anrimian/fafd22d1466767d540fea21e871daa05 to your computer and use it in GitHub Desktop.
MultiTypeAdapter for RecyclerView
public class MultiTypeAdapter extends RecyclerView.Adapter {
private final List<ViewHolderBuilder> builders;
private final List<Item> items;
MultiTypeAdapter(List<Item> items, List<ViewHolderBuilder> builders) {
this.items = items;
this.builders = builders;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
return builders.get(viewType).createViewHolder(inflater, parent);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Item item = items.get(position);
for (int i = 0; i < builders.size(); i++) {
ViewHolderBuilder builder = builders.get(i);
Class itemClass = builder.getItemClass();
if (itemClass.isInstance(item)) {
//noinspection unchecked
builder.bindViewHolder(holder, item);
return;
}
}
throw new IllegalStateException("holder for type not found: " + item);
}
@Override
public int getItemCount() {
return items.size();
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List payloads) {
if (payloads.isEmpty()) {
onBindViewHolder(holder, position);
} else {
Item item = items.get(position);
for (int i = 0; i < builders.size(); i++) {
ViewHolderBuilder builder = builders.get(i);
Class itemClass = builder.getItemClass();
if (itemClass.isInstance(item)) {
for (Object payload: payloads) {
//noinspection unchecked
builder.updateViewHolder(holder, item, payload);
}
return;
}
}
throw new IllegalStateException("holder for type not found: " + item);
}
}
@Override
public int getItemViewType(int position) {
Item item = items.get(position);
for (int i = 0; i < builders.size(); i++) {
ViewHolderBuilder builder = builders.get(i);
Class itemClass = builder.getItemClass();
if (itemClass.isInstance(item)) {
return i;
}
}
throw new IllegalStateException("holder for type not found: " + item);
}
public static class Builder {
private final List<ViewHolderBuilder> builders = new ArrayList<>();
private final List<Item> items;
public Builder(List<Item> items) {
this.items = items;
}
public <T extends RecyclerView.ViewHolder, E> Builder with(
@Nonnull Class<E> itemClass,
@Nonnull HolderCreator<T> holderCreator,
@Nonnull HolderBinder<T, E> holderBinder,
@Nullable HolderUpdater<T, E> holderUpdater) {
builders.add(new ViewHolderBuilder<>(itemClass, holderCreator, holderBinder, holderUpdater));
return this;
}
public <T extends RecyclerView.ViewHolder, E> Builder with(
@Nonnull Class<E> itemClass,
@Nonnull HolderCreator<T> holderCreator,
@Nonnull HolderBinder<T, E> holderBinder) {
return with(itemClass, holderCreator, holderBinder, null);
}
public MultiTypeAdapter build() {
return new MultiTypeAdapter(items, builders);
}
}
private static class ViewHolderBuilder<T extends RecyclerView.ViewHolder, E> {
private @Nonnull Class<E> itemClass;
private @Nonnull HolderCreator<T> holderCreator;
private @Nonnull HolderBinder<T, E> holderBinder;
private @Nullable HolderUpdater<T, E> holderUpdater;
ViewHolderBuilder(@Nonnull Class<E> itemClass,
@Nonnull HolderCreator<T> holderCreator,
@Nonnull HolderBinder<T, E> holderBinder,
@Nullable HolderUpdater<T, E> holderUpdater) {
this.itemClass = itemClass;
this.holderCreator = holderCreator;
this.holderBinder = holderBinder;
this.holderUpdater = holderUpdater;
}
@Nonnull Class<E> getItemClass() {
return itemClass;
}
@Nonnull T createViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) {
return holderCreator.createViewHolder(inflater, parent);
}
void bindViewHolder(T holder, E item) {
holderBinder.bindViewHolder(holder, item);
}
void updateViewHolder(T holder, E item, Object payload) {
if (holderUpdater == null) {
throw new NullPointerException("holder updater not implemented for holder: " + holder);
}
holderUpdater.updateViewHolder(holder, item, payload);
}
}
public interface HolderCreator<T> {
T createViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent);
}
public interface HolderBinder<T extends RecyclerView.ViewHolder, E> {
void bindViewHolder(T holder, E item);
}
public interface HolderUpdater<T extends RecyclerView.ViewHolder, E> {
void updateViewHolder(T holder, E item, Object payload);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment