Adapter 的使用 2
多布局
对于多布局,提供了:
BaseMultiItemQuickAdapter、BaseDelegateMultiAdapter、BaseProviderMultiAdapter
三种基础类型。
1、BaseMultiItemQuickAdapter
说明:适用于类型较少,业务不复杂的场景,便于快速使用。
所有的数据类型,都必须实现MultiItemEntity接口(注意,这里不是继承抽象类,而是实现接口,避免对业务的实体类带来影响)
public class MultipleItemQuickAdapter extends BaseMultiItemQuickAdapter<QuickMultipleEntity, BaseViewHolder> {
public MultipleItemQuickAdapter(List<QuickMultipleEntity> data) {
super(data);
// 绑定 layout 对应的 type
addItemType(QuickMultipleEntity.TEXT, R.layout.item_text_view);
addItemType(QuickMultipleEntity.IMG, R.layout.item_image_view);
addItemType(QuickMultipleEntity.IMG_TEXT, R.layout.item_img_text_view);
}
@Override
protected void convert(@NonNull BaseViewHolder helper, QuickMultipleEntity item) {
// 根据返回的 type 分别设置数据
switch (helper.getItemViewType()) {
case QuickMultipleEntity.TEXT:
helper.setText(R.id.tv, item.getContent());
break;
case QuickMultipleEntity.IMG_TEXT:
...
...
break;
default:
break;
}
}
}
数据实体类写法:
class 你的数据实体类 implements MultiItemEntity {
// 你的数据内容
...
...
/**
* 实现此方法,返回类型
*/
@Override
public int getItemType() {
return itemType;
}
}
2、BaseDelegateMultiAdapter
说明:通过代理类的方式,返回布局 id 和 item 类型;
适用于: 1、实体类不方便扩展,此Adapter的数据类型可以是任意类型,只需要在BaseMultiTypeDelegate.getItemType中返回对应类型 2、item 类型较少 如果类型较多,为了方便隔离各类型的业务逻辑,推荐使用BaseProviderMultiAdapter
方式一:
public class DelegateMultiAdapter extends BaseDelegateMultiAdapter<DelegateMultiEntity, BaseViewHolder> {
public DelegateMultiAdapter() {
super();
// 第一步,设置代理
setMultiTypeDelegate(new BaseMultiTypeDelegate<DelegateMultiEntity>() {
@Override
public int getItemType(@NotNull List<? extends DelegateMultiEntity> data, int position) {
// 根据数据,自己判断应该返回的类型
switch (position % 3) {
case 0:
return DelegateMultiEntity.TEXT;
case 1:
return DelegateMultiEntity.IMG;
case 2:
return DelegateMultiEntity.IMG_TEXT;
default:
break;
}
return 0;
}
});
// 第二部,绑定 item 类型
getMultiTypeDelegate()
.addItemType(DelegateMultiEntity.TEXT, R.layout.item_text_view)
.addItemType(DelegateMultiEntity.IMG, R.layout.item_image_view)
.addItemType(DelegateMultiEntity.IMG_TEXT, R.layout.item_img_text_view);
}
@Override
protected void convert(@NotNull BaseViewHolder helper, @NotNull DelegateMultiEntity item) {
switch (helper.getItemViewType()) {
case QuickMultipleEntity.TEXT:
helper.setText(R.id.tv, "CymChad " + helper.getAdapterPosition());
break;
case QuickMultipleEntity.IMG_TEXT:
switch (helper.getLayoutPosition() % 2) {
case 0:
helper.setImageResource(R.id.iv, R.mipmap.animation_img1);
break;
case 1:
helper.setImageResource(R.id.iv, R.mipmap.animation_img2);
break;
default:
break;
}
helper.setText(R.id.tv, "ChayChan " + helper.getAdapterPosition());
break;
default:
break;
}
}
}
方式二:
public class DelegateMultiAdapter extends BaseDelegateMultiAdapter<DelegateMultiEntity, BaseViewHolder> {
public DelegateMultiAdapter() {
super();
// 实现自己的代理类:
setMultiTypeDelegate(new MyMultiTypeDelegate());
}
@Override
protected void convert(@NotNull BaseViewHolder helper, @NotNull DelegateMultiEntity item) {
switch (helper.getItemViewType()) {
case QuickMultipleEntity.TEXT:
helper.setText(R.id.tv, "CymChad " + helper.getAdapterPosition());
break;
case QuickMultipleEntity.IMG_TEXT:
switch (helper.getLayoutPosition() % 2) {
case 0:
helper.setImageResource(R.id.iv, R.mipmap.animation_img1);
break;
case 1:
helper.setImageResource(R.id.iv, R.mipmap.animation_img2);
break;
default:
break;
}
helper.setText(R.id.tv, "ChayChan " + helper.getAdapterPosition());
break;
default:
break;
}
}
// 方式二:实现自己的代理类
final static class MyMultiTypeDelegate extends BaseMultiTypeDelegate<DelegateMultiEntity> {
public MyMultiTypeDelegate() {
// 绑定 item 类型
addItemType(DelegateMultiEntity.TEXT, R.layout.item_text_view);
addItemType(DelegateMultiEntity.IMG, R.layout.item_image_view);
addItemType(DelegateMultiEntity.IMG_TEXT, R.layout.item_img_text_view);
}
@Override
public int getItemType(@NotNull List<? extends DelegateMultiEntity> data, int position) {
switch (position % 3) {
case 0:
return DelegateMultiEntity.TEXT;
case 1:
return DelegateMultiEntity.IMG;
case 2:
return DelegateMultiEntity.IMG_TEXT;
default:
break;
}
return 0;
}
}
}
3、BaseProviderMultiAdapter
说明:当有多种条目的时候,避免在convert()中做太多的业务逻辑,把逻辑放在对应的 ItemProvider 中。以及最大化自定义VH类型。
1、此Adapter的数据类型可以是任意类型,只需要在getItemType中返回对应类型 2、Adapter不限定ViewHolder类型。ViewHolder 由 BaseItemProvider 实现,并且每个BaseItemProvider可以拥有自己类型的ViewHolder类型。
第一步,Adapter代码如下:
public class ProviderMultiAdapter extends BaseProviderMultiAdapter<ProviderMultiEntity> {
public ProviderMultiAdapter() {
super();
// 注册 Provider
addItemProvider(new ImgItemProvider());
addItemProvider(new TextImgItemProvider());
addItemProvider(new TextItemProvider());
}
/**
* 自行根据数据、位置等信息,返回 item 类型
*/
@Override
protected int getItemType(@NotNull List<? extends ProviderMultiEntity> data, int position) {
switch (position % 3) {
case 0:
return ProviderMultiEntity.IMG;
case 1:
return ProviderMultiEntity.TEXT;
case 2:
return ProviderMultiEntity.IMG_TEXT;
default:
break;
}
return 0;
}
}
第二步,Provider代码如下:
public class ImgItemProvider extends BaseItemProvider<ProviderMultiEntity> {
// item 类型
@Override
public int getItemViewType() {
return ProviderMultiEntity.IMG;
}
// 返回 item 布局 layout
@Override
public int getLayoutId() {
return R.layout.item_image_view;
}
/*
* (可选)
* 重写返回自己的 ViewHolder。
* 默认返回 BaseViewHolder()
*/
@NotNull
@Override
public BaseViewHolder onCreateViewHolder(@NotNull ViewGroup parent) {
return super.onCreateViewHolder(parent);
}
@Override
public void convert(@NotNull BaseViewHolder helper, @NotNull ProviderMultiEntity data) {
// 设置 item 数据
if (helper.getAdapterPosition() % 2 == 0) {
helper.setImageResource(R.id.iv, R.mipmap.animation_img1);
} else {
helper.setImageResource(R.id.iv, R.mipmap.animation_img2);
}
}
// 点击 item 事件
@Override
public void onClick(@NotNull BaseViewHolder helper, @NotNull View view, ProviderMultiEntity data, int position) {
Tips.show("Click: " + position);
}
@Override
public boolean onLongClick(@NotNull BaseViewHolder helper, @NotNull View view, ProviderMultiEntity data, int position) {
Tips.show("Long Click: " + position);
return true;
}
}
BaseSectionQuickAdapter
说明:快速实现带头部的 Adapter,由于本质属于多布局,所以继承自 BaseMultiItemQuickAdapter。(只有一种布局类型的头部!)
数据实体类不再是实现MultiItemEntity接口!!!
为了方便快速使用,对MultiItemEntity进行了再次封装。
情况分别为下:
1、Kotlin实现SectionEntity接口!
1、Java则继承JSectionEntity抽象类!
JSectionEntity是实现于SectionEntity接口,java进了再一次的封装是因为:
SectionEntity接口是使用Kotlin编写的,里面对接口方法进行了默认实现,一般情况下,使用者的数据实体类不需要重写此方法,而java7 无法具有接口默认实现的特性,这就导致使用者必须自己重写此方法。所以 java 使用抽象类进行了再次封装,在抽象类中进行了默认实现。
此种处理处理措施,必定影响使用者 java 数据类的类继承问题,对此表示抱歉,由于java特性的缺失,不得不做出的妥协。如果实在无法继承JSectionEntity抽象类,请自己再次封装一下,或者请使用BaseDelegateMultiAdapter自行参考实现Section。
1、快速使用
Adapter代码如下:
public class SectionQuickAdapter extends BaseSectionQuickAdapter<MySection, BaseViewHolder> {
/**
* 构造方法里, super()必须设置 header layout
* data可有可无
*/
public SectionQuickAdapter(int layoutResId, int sectionHeadResId, List<MySection> data) {
super(sectionHeadResId, data);
// 设置普通item布局(如果item类型只有一种,使用此方法)
setNormalLayout(layoutResId);
// 注册需要点击的子view id
addChildClickViewIds(R.id.more);
}
/**
* 设置header数据
*/
@Override
protected void convertHeader(@NotNull BaseViewHolder helper, @NotNull MySection item) {
if (item != null && item.getObject() instanceof String) {
helper.setText(R.id.header, (String) item.getObject());
}
}
@Override
protected void convert(@NotNull BaseViewHolder helper, MySection item) {
//设置item数据
Video video = (Video) item.getObject();
helper.setText(R.id.tv, video.getName());
}
}
实体类的写法:
/**
* java 写法
*/
public class MySection extends JSectionEntity {
// 你的数据内容
private boolean isHeader;
private Object object;
public MySection(boolean isHeader, Object object) {
this.isHeader = isHeader;
this.object = object;
}
public Object getObject() {
return object;
}
/**
* 重写此方法,返回 boolen 值,告知是否是header
*/
@Override
public boolean isHeader() {
return isHeader;
}
}
/**
* kotlin 写法
*/
class DataBean: SectionEntity {
// 你的数据实体内容
...
...
/**
* 重写此方法,返回 boolen 值,告知是否是header
*/
override val isHeader: Boolean
get() {
// 根据数据实体内的数据,判断是否是header
return false
}
}
2、多布局类型 BaseSectionQuickAdapter
Adapter代码如下:
public class SectionQuickAdapter extends BaseSectionQuickAdapter<MySection, BaseViewHolder> {
/**
* 构造方法里, super()必须设置 header layout
* data可有可无
*/
public SectionQuickAdapter(int layoutResId, int sectionHeadResId, List<MySection> data) {
super(sectionHeadResId, data);
// (只有这里有变化)
// 添加 item 布局、类型
addItemType(类型, 你的布局id_1)
addItemType(类型2, 你的布局id_2)
}
/**
* 设置header数据
*/
@Override
protected void convertHeader(@NotNull BaseViewHolder helper, @NotNull MySection item) {
}
@Override
protected void convert(@NotNull BaseViewHolder helper, MySection item) {
//设置item数据
}
}
数据实体类,多了重写itemType方法:
/**
* java 写法
*/
public class MySection extends JSectionEntity {
private boolean isHeader;
private Object object;
public MySection(boolean isHeader, Object object) {
this.isHeader = isHeader;
this.object = object;
}
public Object getObject() {
return object;
}
/**
* 重写此方法,返回 boolen 值,告知是否是header
*/
@Override
public boolean isHeader() {
return isHeader;
}
/**
* 重写此方法,返回你的item类型
*/
@Override
public int getItemType() {
if (isHeader()) {
return SectionEntity.Companion.HEADER_TYPE;
} else {
// 重写此处,返回自己的多布局类型
return ...;
}
}
}
/**
* kotlin
*/
class DataBean : SectionEntity {
// 你的数据实体内容
...
...
/**
* 重写此方法,返回 boolen 值,告知是否是header
*/
override val isHeader: Boolean
get() {
return false
}
/**
* 重写此方法,返回你的item类型
*/
override val itemType: Int
get() {
if (isHeader) {
return SectionEntity.HEADER_TYPE
} else {
// 根据数据内容,返回你自己的类型
return ...
}
}
}