前言:各位是否有过自己封装通用Adapter,是否使用过第三方的框架,是不是感觉使用别人的框架有很多限制,过度封装让你使用的不爽,解锁的姿势不多,那强烈建议你看完本文章,并clone项目,运行一下,再看看源码(源码超级简单,关键就三个类,包你看懂,还有收获,看不懂找我),我的伪封装可以刷新你对RecyclerView Adapter 的认识,并可以给你无限的意赢空间,解锁你能想到的任意姿势。
先给大家铺垫一下,伪框架的由来:刚到新公司,发现新同事对RecyclerView不是特别熟悉,以至于他在自定义Adapter的时候写了一段错误,但却特别有意思的代码,让我重新对RecyclerView的Adapter有了新的认识,也正因为他的有意思的代码才有了今天我这个 RecyclerView的通用Adapter伪封装,说句体外话,现在这个伪框架已经在公司用起来了,别提多爽。 具体请往下看。
以前我们正常的使用Adapter
这里只列出部分关键代码
解释:正常来说我们定义多样式RecyclerView的Adapter时,我们会先定义一些itemtype,然后通过判断不同的type,创建相应的ViewHolder及view,在onBindViewHolder()处理相应的逻辑。
//重写getItemViewType方法 根据条件返回条目的类型
@Override
public int getItemViewType(int position) {
MoreTypeBean moreTypeBean = mData.get(position);
if (moreTypeBean.type == 0) {
return TYPE_PULL_IMAGE;
} else if (moreTypeBean.type == 1) {
return TYPE_RIGHT_IMAGE;
} else {
return TYPE_THREE_IMAGE;
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//创建不同的 ViewHolder
View view;
//根据viewtype来判断
if (viewType == TYPE_PULL_IMAGE) {
view =View.inflate(parent.getContext(),R.layout.item_pull_img,null);
return new PullImageHolder(view);
} else if (viewType == TYPE_RIGHT_IMAGE) {
view =View.inflate(parent.getContext(),R.layout.item_right_img,null);
return new RightImageHolder(view);
} else {
view =View.inflate(parent.getContext(),R.layout.item_three_img,null);
return new ThreeImageHolder(view);
}
}
他写的(这里我只罗列一些伪代码,表达他的大概意思)
//重写getItemViewType方法 根据条件返回条目的类型
@Override
public int getItemViewType(int position) {
//这里是关键点所在
if (position == 0) {
return R.layout.layout_a;
} else if (position == 1) {
return R.layout.layout_b;
} else {
return R.layout.layout_c;
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new GViewHolder(View.inflate(parent.getContext(),viewType))
}
@Override
public void onBindViewHolder(GViewHolder holder, int position) {
if (holder.item == R.layout.layout_a) {
//todo layout_a处理逻辑
} else if (item == R.layout.layout_b) {
//todo 处理layout_b 逻辑
} else if (item == R.layout.layout_c) {
//todo 处理layout_c 逻辑
}
}
当时看到他这段代码心里想法的变化:
第一眼,果然对RecyclerView 不熟,基本的使用都写的有问题
->
再仔细一想,结果是对的啊,而且不用再定义type常量,不用再定义过多的viewHolder
->
再多看几眼,我被他这种另类的写法征服了。
->
于是我重新写了RecyclerView的通用Adapter封装,也就有了今天的RecyclerView的通用Adapter伪封装,却给你无比巨大的意赢空间
感悟(这段文字有点多,慢慢看,体会,很有意思):仔细对比正常写法和他写的,你会发现根据Google官方对方法的定义,确实他写的是一段错误代码,但是仔细看他的代码你会发现很有意思,为什么呢?在getItemViewType()将布局资源ID,直接返回,在onBindViewHolder(GViewHolder holder, int position)方法直接从holder中将布局的资源ID拿出来做判断,做相应的逻辑,看下来少了很多代码,逻辑比以前的写法更加清晰了,简洁。
我敢肯定看到这里,你可能心里还是懵的,不就是将LayoutId作为ItemType直接返回了吗,那么请你到我的源码中看看,我保证你看的懂,而且会感觉发现新大陆
RVAdapter-master
我的伪封装关键只有三个类所以代码我就不讲了,大家进源码看看
我这个伪框架的使用
单样式使用:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_view);
rvContent = findViewById(R.id.rv_content);
RVSimpleAdapter adapter = new RVSimpleAdapter<String>(this, getDatas(), R.layout.item_simple) {
@Override
public void convert(ViewHolder holder, String item) {
holder.setText(R.id.tv_name, item);
}
};
//垂直
adapter.attachLinearRv(rvContent, RVSimpleAdapter.VERTICAL);
//水平
// adapter.attachLinearRv(rvContent, RVSimpleAdapter.HORIZONTAL);
//自定义
// rvContent.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
// rvContent.setItemAnimator(new DefaultItemAnimator());
// rvContent.setAdapter(adapter);
}

多样式使用
继承实现
class MultiAdater extends RvBaseAdapter<Integer> {
MultiAdater(Context context, List<Integer> datas) {
super(context, datas);
}
@Override
public int getLayoutId(int position, Integer item) {
return item % 2 == 0 ? R.layout.item_simple : R.layout.item_red_background;
}
@Override
public void convert(ViewHolder holder, Integer item, int layoutId, int position) {
switch (layoutId) {
case R.layout.item_simple:
holder.setText(R.id.tv_name, String.format("样式一 item: %s", item));
break;
case R.layout.item_red_background:
holder.setText(R.id.tv_content, String.format("样式二 item: %s", item));
break;
default:
break;
}
}
}
简单使用
new MultiAdater(this, getDatas()).attachLinearRv(recyclerView, RVSimpleAdapter.VERTICAL);

布局多样式,并且数据源是多种对象
class ExtraAdater extends RvBaseAdapter<Object> {
ExtraAdater(Context context, List<Object> datas) {
super(context, datas);
}
@Override
public int getLayoutId(int position, Object item) {
if (item instanceof A) {
return R.layout.item_simple;
} else {
return R.layout.item_red_background;
}
}
@Override
public void convert(ViewHolder holder, Object item, int layoutId, int position) {
if (item instanceof A) {
holder.setText(R.id.tv_name, String.format("对象: %s", ((A) item).name));
} else {
holder.setText(R.id.tv_content, String.format("对象: %s", ((B) item).name));
}
}
}

到这里我的伪框架(伪封装,半封装)的使用就完了,当然其实还封装了很多通用方法,实例代码就没有展示了,有兴趣去看看ViewHolder就可以看到了,使用都简单
最后说一句,如果大家看的不是很懂,真的强烈建议大家clone我的项目跑一下,看看源码,我保证你还是有所获,若对你有帮助请star或是fork,这是对猿人最大的鼓励
网友评论