支持各种ViewHolder类型的RecyclerView.Adapter的实现,是一个万能适配器
项目地址:https://github.com/simplify20/PowerfulRecyclerViewAdapter
欢迎star,fork,提issue.
特性:
新特性:
Added in 2016-4-10:
新增 @DataBean 注解,目前在[dev分支]上
使用类似Dagger2和DataBinding的编译期注解处理器,在编译器根据模板生成DataBean代码(模板引擎),这样可以省去编写DataBean的成本。
参考下文[使用DataBean注解]
dev分支
tips:图片看不清可右键另存或新标签页打开后查看
class CommonRecyclerAdapter
:万能适配器,支持插入和删除数据,支持任意类型的ViewHolder(限于RecyclerView)
interface DisplayBean
:用于创建ViewHolder
interface DataBean
:扩展了DisplayBean接口,可以绑定数据到ViewHolder,也可以创建ViewHolder,是数据与ViewHolder之间的桥梁
protected CommonRecyclerAdapter adapter;
...
recyclerView.setAdapter(adapter);
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));
}
}
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()));
}
}
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的代码很少,且都是样板代码,为了简单省事,所以采用代码生成器来生成这部分代码。而生成代码的工具是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的几个属性:
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.
Email:[email protected]
Weibo:http://weibo.com/u/3398987850
Github:https://github.com/simplify20
CSDN:http://blog.csdn.net/u012825445