@Override public void withClassLinker(@NonNull ClassLinker<T> classLinker) { checkNotNull(classLinker); doRegister(ClassLinkerWrapper.wrap(classLinker, binders)); }
@Override public int getNewListSize() { return mNewItems != null ? mNewItems.size() : 0; }
@Override public void withLinker(@NonNull Linker<T> linker) { checkNotNull(linker); doRegister(linker); }
@Test(expected = IllegalStateException.class) public void shouldThrowIllegalStateException() { MultiTypeAdapter adapter = new MultiTypeAdapter(); Items empty = new Items(); adapter.setItems(empty); TestItemViewBinder binder = new TestItemViewBinder(); empty.add(new TestItem("ItemViewBinderTest")); binder.notifyTestItemAdded(); adapter.register(TestItem.class, binder); }
@Test public void testOnCreateViewHolder() { MultiTypeAdapter adapter = new MultiTypeAdapter(); adapter.register(TestItem.class, mockedItemViewBinder); TestItem item = new TestItem("testOnCreateViewHolder"); adapter.setItems(Collections.singletonList(item)); int type = adapter.getItemViewType(0); adapter.onCreateViewHolder(parent, type); verify(mockedItemViewBinder).onCreateViewHolder(inflater, parent); }
@Test public void shouldNotOverrideRegisteredBinderWhenToMany() { MultiTypeAdapter adapter = new MultiTypeAdapter(); TestItemViewBinder binder2 = new TestItemViewBinder(); adapter.register(TestItem.class) .to(itemViewBinder, binder2) .withLinker(new Linker<TestItem>() { @Override public int index(int position, @NonNull TestItem testItem) { // ignored return -1; } }); assertEquals(TestItem.class, adapter.getTypePool().getClass(0)); assertEquals(TestItem.class, adapter.getTypePool().getClass(1)); assertEquals(itemViewBinder, adapter.getTypePool().getItemViewBinder(0)); assertEquals(binder2, adapter.getTypePool().getItemViewBinder(1)); }
@Test public void shouldOverrideRegisteredBinder() { MultiTypeAdapter adapter = new MultiTypeAdapter(); adapter.register(TestItem.class, itemViewBinder); assertEquals(1, adapter.getTypePool().size()); assertEquals(itemViewBinder, adapter.getTypePool().getItemViewBinder(0)); TestItemViewBinder newBinder = new TestItemViewBinder(); adapter.register(TestItem.class, newBinder); assertEquals(newBinder, adapter.getTypePool().getItemViewBinder(0)); }
/** * 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>()); }
private void doRegister(@NonNull Linker<T> linker) { for (ItemViewBinder<T, ?> binder : binders) { adapter.register(clazz, binder, linker); } } }
@Before public void register() { pool = new MultiTypePool(); pool.register(TestItem.class, new TestItemViewBinder(), new DefaultLinker<TestItem>()); pool.register(RegisteredSubClass.class, new TestItemViewBinder(), new DefaultLinker<TestItem>()); }
/** * Called to return the stable ID for the item, and passes the event to its associated binder. * * @param position Adapter position to query * @return the stable ID of the item at position * @see ItemViewBinder#getItemId(Object) * @see RecyclerView.Adapter#setHasStableIds(boolean) * @since v3.2.0 */ @Override @SuppressWarnings("unchecked") public final long getItemId(int position) { Object item = items.get(position); int itemViewType = getItemViewType(position); ItemViewBinder binder = typePool.getItemViewBinder(itemViewType); return binder.getItemId(item); }
int indexInTypesOf(int position, @NonNull Object item) throws BinderNotFoundException { int index = typePool.firstIndexOf(item.getClass()); if (index != -1) { @SuppressWarnings("unchecked") Linker<Object> linker = (Linker<Object>) typePool.getLinker(index); return index + linker.index(position, item); } throw new BinderNotFoundException(item.getClass()); }
@Override public final ViewHolder onCreateViewHolder(ViewGroup parent, int indexViewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); ItemViewBinder<?, ?> binder = typePool.getItemViewBinder(indexViewType); return binder.onCreateViewHolder(inflater, parent); }
/** * Called when a view created by this adapter has been recycled, and passes the event to its * associated binder. * * @param holder The ViewHolder for the view being recycled * @see RecyclerView.Adapter#onViewRecycled(ViewHolder) * @see ItemViewBinder#onViewRecycled(ViewHolder) */ @Override @SuppressWarnings("unchecked") public final void onViewRecycled(@NonNull ViewHolder holder) { getRawBinderByViewHolder(holder).onViewRecycled(holder); }
/** * Called when a view created by this adapter has been attached to a window, and passes the * event to its associated item view binder. * * @param holder Holder of the view being attached * @see RecyclerView.Adapter#onViewAttachedToWindow(ViewHolder) * @see ItemViewBinder#onViewAttachedToWindow(ViewHolder) */ @Override @SuppressWarnings("unchecked") public final void onViewAttachedToWindow(@NonNull ViewHolder holder) { getRawBinderByViewHolder(holder).onViewAttachedToWindow(holder); }
/** * Called when a view created by this adapter has been detached from its window, and passes * the event to its associated item view binder. * * @param holder Holder of the view being detached * @see RecyclerView.Adapter#onViewDetachedFromWindow(ViewHolder) * @see ItemViewBinder#onViewDetachedFromWindow(ViewHolder) */ @Override @SuppressWarnings("unchecked") public final void onViewDetachedFromWindow(@NonNull ViewHolder holder) { getRawBinderByViewHolder(holder).onViewDetachedFromWindow(holder); }
/** * Constructs a MultiTypeAdapter with a items list and an initial capacity of TypePool. * * @param items the items list * @param initialCapacity the initial capacity of TypePool */ public MultiTypeAdapter(@NonNull List<?> items, int initialCapacity) { this(items, new MultiTypePool(initialCapacity)); }
@Override public final int getItemViewType(int position) { Object item = items.get(position); return indexInTypesOf(position, item); }
/** * 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; }
@Override public int getOldListSize() { return mOldItems != null ? mOldItems.size() : 0; }