/** * Constructs a MultiTypeAdapter with a items list and a TypePool. * * @param items the items list * @param pool the type pool */ public MultiTypeAdapter(@NonNull List<?> items, @NonNull TypePool pool) { checkNotNull(items); checkNotNull(pool); this.items = items; this.typePool = pool; }
/** * Sets and updates the items atomically and safely. It is recommended to use this method * to update the items with a new wrapper list or consider using {@link CopyOnWriteArrayList}. * * <p>Note: If you want to refresh the list views after setting items, you should * call {@link RecyclerView.Adapter#notifyDataSetChanged()} by yourself.</p> * * @param items the new items list * @since v2.4.1 */ public void setItems(@NonNull List<?> items) { checkNotNull(items); this.items = items; }
/** * Set the TypePool to hold the types and view binders. * * @param typePool the TypePool implementation */ public void setTypePool(@NonNull TypePool typePool) { checkNotNull(typePool); this.typePool = typePool; }
@Override public <T> void register( @NonNull Class<? extends T> clazz, @NonNull ItemViewBinder<T, ?> binder, @NonNull Linker<T> linker) { checkNotNull(clazz); checkNotNull(binder); checkNotNull(linker); classes.add(clazz); binders.add(binder); linkers.add(linker); }
/** * Constructs a MultiTypePool with specified lists. * * @param classes the list for classes * @param binders the list for binders * @param linkers the list for linkers */ public MultiTypePool( @NonNull List<Class<?>> classes, @NonNull List<ItemViewBinder<?, ?>> binders, @NonNull List<Linker<?>> linkers) { checkNotNull(classes); checkNotNull(binders); checkNotNull(linkers); this.classes = classes; this.binders = binders; this.linkers = linkers; }
@Override public int firstIndexOf(@NonNull final Class<?> clazz) { checkNotNull(clazz); int index = classes.indexOf(clazz); if (index != -1) { return index; } for (int i = 0; i < classes.size(); i++) { if (classes.get(i).isAssignableFrom(clazz)) { return i; } } return -1; }
@Override @CheckResult @SafeVarargs public final @NonNull OneToManyEndpoint<T> to(@NonNull ItemViewBinder<T, ?>... binders) { checkNotNull(binders); this.binders = binders; return this; }
@Override public void withLinker(@NonNull Linker<T> linker) { checkNotNull(linker); doRegister(linker); }
@Override public boolean unregister(@NonNull Class<?> clazz) { checkNotNull(clazz); boolean removed = false; while (true) { int index = classes.indexOf(clazz); if (index != -1) { classes.remove(index); binders.remove(index); linkers.remove(index); removed = true; } else { break; } } return removed; }
/** * Makes the exception to occur in your class for debug and index. * * @param adapter the MultiTypeAdapter * @param items the items list * @throws BinderNotFoundException if check failed * @throws IllegalArgumentException if your Items/List is empty */ @SuppressWarnings("unchecked") public static void assertAllRegistered(@NonNull MultiTypeAdapter adapter, @NonNull List<?> items) throws BinderNotFoundException, IllegalArgumentException, IllegalAccessError { checkNotNull(adapter); checkNotNull(items); if (items.isEmpty()) { throw new IllegalArgumentException("Your Items/List is empty."); } for (int i = 0; i < items.size(); i++) { adapter.indexInTypesOf(i, items.get(0)); } /* All passed. */ }
/** * @param recyclerView the RecyclerView * @param adapter the MultiTypeAdapter * @throws IllegalAccessError The assertHasTheSameAdapter() method must be placed after * recyclerView.setAdapter(). * @throws IllegalArgumentException If your recyclerView's adapter. * is not the sample with the argument adapter. */ public static void assertHasTheSameAdapter(@NonNull RecyclerView recyclerView, @NonNull MultiTypeAdapter adapter) throws IllegalArgumentException, IllegalAccessError { checkNotNull(recyclerView); checkNotNull(adapter); if (recyclerView.getAdapter() == null) { throw new IllegalAccessError("The assertHasTheSameAdapter() method must " + "be placed after recyclerView.setAdapter()"); } if (recyclerView.getAdapter() != adapter) { throw new IllegalArgumentException( "Your recyclerView's adapter is not the sample with the argument adapter."); } } }
@Override public void withClassLinker(@NonNull ClassLinker<T> classLinker) { checkNotNull(classLinker); doRegister(ClassLinkerWrapper.wrap(classLinker, binders)); }
/** * Registers a type class and its item view binder. If you have registered the class, * it will override the original binder(s). Note that the method is non-thread-safe * so that you should not use it in concurrent operation. * <p> * Note that the method should not be called after * {@link RecyclerView#setAdapter(RecyclerView.Adapter)}, or you have to call the setAdapter * again. * </p> * * @param clazz the class of a item * @param binder the item view binder * @param <T> the item data type */ public <T> void register(@NonNull Class<? extends T> clazz, @NonNull ItemViewBinder<T, ?> binder) { checkNotNull(clazz); checkNotNull(binder); checkAndRemoveAllTypesIfNeeded(clazz); register(clazz, binder, new DefaultLinker<T>()); }
/** * Registers a type class to multiple item view binders. If you have registered the * class, it will override the original binder(s). Note that the method is non-thread-safe * so that you should not use it in concurrent operation. * <p> * Note that the method should not be called after * {@link RecyclerView#setAdapter(RecyclerView.Adapter)}, or you have to call the setAdapter * again. * </p> * * @param clazz the class of a item * @param <T> the item data type * @return {@link OneToManyFlow} for setting the binders * @see #register(Class, ItemViewBinder) */ @CheckResult public @NonNull <T> OneToManyFlow<T> register(@NonNull Class<? extends T> clazz) { checkNotNull(clazz); checkAndRemoveAllTypesIfNeeded(clazz); return new OneToManyBuilder<>(this, clazz); }
/** * Registers all of the contents in the specified type pool. If you have registered a * class, it will override the original binder(s). Note that the method is non-thread-safe * so that you should not use it in concurrent operation. * <p> * Note that the method should not be called after * {@link RecyclerView#setAdapter(RecyclerView.Adapter)}, or you have to call the setAdapter * again. * </p> * * @param pool type pool containing contents to be added to this adapter inner pool * @see #register(Class, ItemViewBinder) * @see #register(Class) */ public void registerAll(@NonNull final TypePool pool) { checkNotNull(pool); final int size = pool.size(); for (int i = 0; i < size; i++) { registerWithoutChecking( pool.getClass(i), pool.getItemViewBinder(i), pool.getLinker(i) ); } }