PowerfulRecyclerViewAdapter:一种RecyclerView的万能适配器实现
Posted simplify20
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PowerfulRecyclerViewAdapter:一种RecyclerView的万能适配器实现相关的知识,希望对你有一定的参考价值。
PowerfulRecyclerViewAdapter
支持各种ViewHolder类型的RecyclerView.Adapter的实现,是一个万能适配器
项目地址:https://github.com/simplify20/PowerfulRecyclerViewAdapter
欢迎star,fork,提issue.
特性:
- 使用DataBean关联Data(Model)与ViewHolder;
- DataBean控制ViewHolder的创建以及数据到ViewHolder的绑定;
- Adapter的一部分职能由DataBean承担,如创建不同类型的ViewHolder以及绑定数据到ViewHolder,Adapter只用维护数据的相关操作即可;
- Adapter的onCreateViewHolder和onBindViewHolder中没有switch..case语句,通过DataBean的多态性实现不同的创建和绑定;
- 使用了本项目的Adapter,使用RecyclerView时就不用写Adapter了;
- 支持任何种类的ViewHolder(继承自BaseRecyclerViewHolder)
- 使用接口可以提高ViewHolder及Data的复用性,并且利于测试。
新特性:
Added in 2016-4-10:
新增 @DataBean 注解,目前在[dev分支]上
使用类似Dagger2和DataBinding的编译期注解处理器,在编译器根据模板生成DataBean代码(模板引擎),这样可以省去编写DataBean的成本。
参考下文[使用DataBean注解]
类图:
tips:图片看不清可右键另存或新标签页打开后查看
主要类:
class CommonRecyclerAdapter
:万能适配器,支持插入和删除数据,支持任意类型的ViewHolder(限于RecyclerView)
interface DisplayBean
:用于创建ViewHolder
interface DataBean
:扩展了DisplayBean接口,可以绑定数据到ViewHolder,也可以创建ViewHolder,是数据与ViewHolder之间的桥梁
使用步骤:
- 使用CommonRecyclerAdapter作为RecyclerView的Adapter;
protected CommonRecyclerAdapter adapter;
...
recyclerView.setAdapter(adapter);
- 根据item内容,继承BaseDataBean,实现自定义的DataBean;
public class BookTitleBean extends BaseDataBean<Book, BookTitleViewHolder>
public BookTitleBean(Book data)
super(data);
@Override
public BookTitleViewHolder createHolder(ViewGroup parent)
//create an instance of Your ViewHolder
return new BookTitleViewHolder(getView(parent, BookTitleViewHolder.LAYOUT_ID));
- 根据item内容,继承BaseRecyclerViewHolder,实现自定义ViewHolder;
public class BookTitleViewHolder extends BaseRecyclerViewHolder<Book>
//declare LAYOUT_ID
public static final int LAYOUT_ID = R.layout.item_book_title;
private TextView nameTxt;
private TextView priceTxt;
public BookTitleViewHolder(View itemView)
super(itemView);
@Override
protected void initView()
nameTxt = findView(R.id.name);
priceTxt = findView(R.id.price);
@Override
public void setData(Book data)
if (data == null)
return;
nameTxt.setText(data.getName());
priceTxt.setText(String.valueOf(data.getPrice()));
- 构建用于显示的数据集:data set -> displaybean set
protected void initData()
//init displaybean set
List<DisplayBean> bookTitleBeans = new ArrayList<>(20);
//add progress display bean
CommonDisplayBean progressBean = new CommonDisplayBean(R.layout.item_progress);
bookTitleBeans.add(progressBean);
Random random = new Random();
for (int i = 0; i < 20; i++)
if (i % 5 == 0)
//add category
if (i == 0)
//add mock category
MockCategory mockCategory = new MockCategory();
CategoryBean categoryBean = new CategoryBean(mockCategory);
bookTitleBeans.add(categoryBean);
else
Category category = new Category(i / 5, "category" + (i / 5 + 1));
CategoryBean categoryBean = new CategoryBean(category);
bookTitleBeans.add(categoryBean);
float price = random.nextFloat() * 200 + 1.0f;
Book book = new Book(i, "book" + i, (float) (Math.round(price * 100) / 100.0), (i + 50));
BookTitleBean bookTitleBean = new BookTitleBean(book);
bookTitleBeans.add(bookTitleBean);
//load data
adapter.loadData(bookTitleBeans);
效果:
对于只展示静态数据或没有数据(无文字显示)的item,如只显示一个progressBar,使用CommonDisplayBean,默认创建BaseRecyclerViewHolder
复用ViewHolder和DataBean
使用接口关联DateBean和ViewHolder
ICategory
接口/** * Notes: * 1.使用接口以降低耦合,提高ViewHolder及DataBean的复用性 * 2.在有复用需求的情况下,使用接口,没有这样的需求可以使用具体Data类 * 3.这个接口表明了ViewHolder的需求,表明了ViewHolder上要展示的内容,或者潜在的交互 * 4.在服务器接口还没有完成时,可以创建mock实现,以和服务器进行独立开发测试 */ public interface ICategory String getName(); long getId();
CategoryBean
:public class CategoryBean extends BaseDataBean<ICategory, CategoryViewHolder> public CategoryBean(ICategory data) super(data); @Override public CategoryViewHolder createHolder(ViewGroup parent) return new CategoryViewHolder(getView(parent, CategoryViewHolder.LAYOUT_ID));
CategoryViewHolder
public class CategoryViewHolder extends BaseRecyclerViewHolder<ICategory>
public static final int LAYOUT_ID = R.layout.item_book_catagory;
protected TextView categoryNameTxt;
public CategoryViewHolder(View itemView)
super(itemView);
@Override
protected void initView()
categoryNameTxt = findView(R.id.book_category);
@Override
public void setData(ICategory category)
if (category == null)
return;
categoryNameTxt.setText(category.getName());
使用@DataBean注解
因为父类DataBean已经完成了很多工作,具体DataBean的代码很少,且都是样板代码,为了简单省事,所以采用代码生成器来生成这部分代码。而生成代码的工具是holder-compiler:注解处理器,这个我已经写好了,在使用时,你只需用@DataBean注解你的具体ViewHolder,注解处理器会帮你生成所需的代码,非常方便。
使用步骤,以BookTitleViewHolder为例:
//use DataBean annotation to annotate your ViewHolder
@DataBean(beanName = "TestDataBean", data = Book.class)
public class BookTitleViewHolder extends BaseRecyclerViewHolder<Book>
//declare LAYOUT_ID,the name must be LAYOUT_ID
public static final int LAYOUT_ID = R.layout.item_book_title;
private TextView nameTxt;
private TextView priceTxt;
public BookTitleViewHolder(View itemView)
super(itemView);
@Override
protected void initView()
nameTxt = findView(R.id.name);
priceTxt = findView(R.id.price);
@Override
public void setData(Book data)
if (data == null)
return;
nameTxt.setText(data.getName());
priceTxt.setText(String.valueOf(data.getPrice()));
1.继承BaseRecyclerViewHolder创建你的ViewHolder;
注:ViewHolder中LAYOUT_ID字段是必填的,且命名限定为LAYOUT_ID,是一个公有常量,因为生成的代码要引用ViewHolder的这个字段。
2.使用@DataBean注解你的ViewHolder(只能注解类,详见DataBean注解的源码,在holder-annotation module下)
3.DataBean的几个属性:
- beanName->要生成的DataBean的简单类名,String类型;
- data->要绑定的数据的类型,Class类型。
4.build项目,注解处理器会在编译器获得注解信息,并生成代码,生成的TestDataBean如下:
app\\build\\generated\\source\\apt\\debug\\ [package]\\TestDataBean.java
package com.steve.creact.powerfuladapter.presentation.viewholder.databean;
import android.view.ViewGroup;
import com.steve.creact.library.display.BaseDataBean;
import com.steve.creact.powerfuladapter.data.Book;
import com.steve.creact.powerfuladapter.presentation.viewholder.BookTitleViewHolder;
/**
* Generated DataBean for BookTitleViewHolder
* Powered by Holder-Compiler
*/
public class TestDataBean extends BaseDataBean<Book, BookTitleViewHolder>
public TestDataBean(Book data)
super(data);
@Override
public BookTitleViewHolder createHolder(ViewGroup parent)
return new BookTitleViewHolder(getView(parent, BookTitleViewHolder.LAYOUT_ID));//that's why need LAYOUT_ID field in ViewHolder
可见,与手写代码完全一样。
build时可能存在的问题:
holder-compiler.jar无法删除->打开任务管理器,结束java se进程,重新build.
联系我(Contact Me):
Email:creact92@gmail.com
Weibo:http://weibo.com/u/3398987850
Github:https://github.com/simplify20
CSDN:http://blog.csdn.net/u012825445
以上是关于PowerfulRecyclerViewAdapter:一种RecyclerView的万能适配器实现的主要内容,如果未能解决你的问题,请参考以下文章