Zero‑Adapter Multi‑Item RecyclerView Library for Android
This article introduces an open‑source Android library that eliminates the need for custom RecyclerView adapters by using a ViewHolderManager system to handle multiple item types, headers, footers, click listeners, load‑more pagination, and animations, with complete code examples and usage guidelines.
Introduction
RecyclerView is a widely used list component in Android, but handling multiple item layouts often leads to large switch statements in the adapter, making the code hard to maintain. To solve this, the author created an open‑source library (GitHub: https://github.com/free46000/MultiItem) that provides a zero‑coding adapter by decoupling item types from the adapter through a ViewHolderManager mechanism, greatly improving extensibility.
Effect Screenshots
Usage
Multiple‑Type List Usage
Register different ViewHolderManager implementations for each data class and set the mixed data list to the adapter. No need to modify the adapter itself.
// Initialize adapter
BaseItemAdapter adapter = new BaseItemAdapter();
// Register TextBean manager
adapter.register(TextBean.class, new TextViewManager());
// Register ImageTextBean manager
adapter.register(ImageTextBean.class, new ImageAndTextManager());
// Register ImageBean manager
adapter.register(ImageBean.class, new ImageViewManager());
// Assemble data source list
List
list = new ArrayList<>();
list.add(new TextBean("AAA"));
list.add(new ImageBean(R.drawable.img1));
list.add(new ImageTextBean(R.drawable.img2, "BBB" + i));
// Set data and adapter
adapter.setDataItems(list);
recyclerView.setAdapter(adapter);The TextViewManager (and similar managers) contain the full binding logic:
public class ImageViewManager extends BaseViewHolderManager
{
@Override
public void onBindViewHolder(BaseViewHolder holder, ImageBean data) {
ImageView imageView = getView(holder, R.id.image);
imageView.setImageResource(data.getImg());
}
@Override
protected int getItemLayoutId() {
return R.layout.item_image;
}
}Thus the library completely removes the need to extend RecyclerView.Adapter for multi‑type lists.
Same Data Source with Multiple ViewHolders
Useful for chat interfaces where a single message type can be displayed on the left or right. Register a ViewHolderManagerGroup that decides which manager to use based on the data:
BaseItemAdapter adapter = new BaseItemAdapter();
adapter.register(MessageBean.class, new ViewHolderManagerGroup<>(
new SendMessageManager(),
new ReceiveMessageManager()) {
@Override
public int getViewHolderManagerIndex(MessageBean itemData) {
return itemData.getSender().equals(uid) ? 0 : 1;
}
});
recyclerView.setAdapter(adapter);Click Listeners
Set item click and long‑click callbacks directly on the adapter:
adapter.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(BaseViewHolder viewHolder) {
toastUser(String.format("Clicked position %s data: %s",
viewHolder.getItemPosition(), viewHolder.getItemData()));
}
});
adapter.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public void onItemLongClick(BaseViewHolder viewHolder) {
toastUser(String.format("Long‑pressed position %s data: %s",
viewHolder.getItemPosition(), viewHolder.getItemData()));
}
});Header and Footer
Two ways to add headers/footers: addHeadView / addFootView for raw views, or addHeadItem / addFootItem for data items.
// Register TextBean manager
adapter.register(TextBean.class, new TextViewManager());
// Add header view
TextView headView = new TextView(this);
headView.setText("Header added via addHeadView");
adapter.addHeadView(headView);
// Add header item
adapter.addHeadItem(new TextBean("Header added via addHeadItem"));
// Add footer view
TextView footView = new TextView(this);
footView.setText("Footer added via addFootView");
adapter.addFootView(footView);
// Add footer item
adapter.addFootItem(new TextBean("Footer added via addFootItem"));Pull‑to‑Refresh and Load‑More
Enable load‑more (treated as a footer) before calling the method to start loading:
adapter.enableLoadMore(new LoadMoreHolderManager(this::loadData));
adapter.setLoadCompleted(isLoadAll);
adapter.setLoadFailed();The LoadMoreHolderManager defines the layout and state handling:
public class LoadMoreHolderManager extends LoadMoreManager {
public LoadMoreHolderManager(OnLoadMoreListener listener, boolean auto) {
super(listener, auto);
}
@Override
protected int getItemLayoutId() { return R.layout.item_load_more; }
@Override
protected void updateLoadInitView() { ((TextView)getView(loadMoreView,R.id.text)).setText(""); }
@Override
protected void updateLoadingMoreView() { ((TextView)getView(loadMoreView,R.id.text)).setText(R.string.loading_more); }
@Override
protected void updateLoadCompletedView(boolean all) {
((TextView)getView(loadMoreView,R.id.text)).setText(all ? R.string.load_all : R.string.load_has_more);
}
@Override
protected void updateLoadFailedView() { ((TextView)getView(loadMoreView,R.id.text)).setText(R.string.load_failed); }
}Enable Animation
Start item animations and optionally limit them to the first load:
adapter.enableAnimation(baseAnimation, false);
/**
* Set animation duration (default 400ms)
*/
public void setAnimDuration(long duration) { ... }
/**
* Set animation interpolator (default LinearInterpolator)
*/
public void setInterpolator(@NonNull Interpolator interpolator) { ... }Summary
The library provides a clean, generic way to manage multiple RecyclerView item types without writing a custom adapter. By registering ViewHolderManager instances for each data class (or a group of managers for a single class), developers gain decoupled view creation, binding, header/footer support, click handling, pagination, and animation with minimal boilerplate.
Acknowledgements
Thanks to the following open‑source projects for inspiration: recyclerview‑animators MultiType
Qunar Tech Salon
Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.