Created
June 29, 2018 08:38
-
-
Save Anrimian/fafd22d1466767d540fea21e871daa05 to your computer and use it in GitHub Desktop.
MultiTypeAdapter for RecyclerView
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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