该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列。该系列引用了《Android开发艺术探索》以及《深入理解Android 卷Ⅰ,Ⅱ,Ⅲ》中的相关知识,另外也借鉴了其他的优质博客,在此向各位大神表示感谢,膜拜!!!
前言
上文我们很详细的分析了ListView的使用、优化、及ListView的RecycleBin机制,读者如果对ListView不太清楚,那么请参看我的上篇博文。不过呢,Google Material Design提供的RecyclerView已经逐渐的取代ListView。RecyclerView提供了一种插拔式的体验,高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现令人瞠目的效果。
如果说上面的理由只是大而空泛的话,那我们来看以下场景
你想控制数据的显示方式,列表显示、网格显示、瀑布流显示等等,之前你需要ListView,GridView和自定义View,而现在你可以通过RecyclerView的布局管理器LayoutManager控制
你想要控制Item间的间隔(可绘制),想自定义更多样式的分割线,之前你可以设置divider,那么现在你可以使用RecyclerView的ItemDecoration,想怎么画怎么画。
你想要控制Item增删的动画,ListView呢我们只能自己通过属性动画来操作 Item 的视图。RecyclerView可使用ItemAnimator
你想要局部刷新某个Item,对于ListView来说,我们知道notifyDataSetChanged 来通知视图更新变化,但是该方法会重绘每个Item,而对于RecyclerView.Adapter 则提供了 notifyItemChanged 用于更新单个 Item View 的刷新,我们可以省去自己写局部更新的工作。
除了上述场景外,RecyclerView强制使用了ViewHolder模式,我们知道ListView使用ViewHolder来进行性能优化,但是这不是必须得,但是在RecyclerView中是必须的,另外RecyclerView还有许多优势,这里就不一一列举了,总体来说现在越来越多的项目使用RecyclerView,许多老旧项目也渐渐使用RecyclerView来替代ListView。
注:当我们想要一个列表显示控件的时候,需要支持动画,或者频繁更新,局部刷新,建议使用RecyclerView,更加强大完善,易扩展;其他情况下ListView在使用上反而更加方便,快捷。
前言我们就讲到这,那么我们来进入正题。
RecyclerView的使用
作为一个“新”控件,RecyclerView的使用有许多需要注意的地方
RecyclerView的简单使用
一样的我们新建一个Demo来演示RecyclerView的使用
[RecyclerViewDemo1Activity.java]
public class RecyclerViewDemo1Activity extends AppCompatActivity {
@BindView(R.id.recycler_view)
RecyclerView mRecyclerView;
private List<String> mData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_demo1_view);
ButterKnife.bind(this);
//LayoutManager必须指定,否则无法显示数据,这里指定为线性布局,
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
//虚拟数据
mData = createDataList();
//设置Adapter必须指定,否则数据怎么显示
mRecyclerView.setAdapter(new RecyclerViewDemo1Adapter(mData));
}
protected List<String> createDataList() {
mData = new ArrayList<>();
for (int i=0;i<20;i++){
mData.add("这是第"+i+"个View");
}
return mData;
}
}
其对应的布局文件也很简单activity_recycler_demo1_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</android.support.v7.widget.RecyclerView>
</LinearLayout>
那么我们再来看RecyclerViewDemo1Adapter
/**
* 与ListView的Adapter不同,RecyclerView的Adapter需要继承RecyclerView.Adapter<VH>(VH是ViewHolder的类名)
* 记为RecyclerViewDemo1Adapter。
* 创建ViewHolder:在RecyclerViewDemo1Adapter中创建一个继承RecyclerView.ViewHolder的静态内部类,记为ViewHolder
* (RecyclerView必须使用ViewHolder模式,这里的ViewHolder实现几乎与ListView优化时所使用的ViewHolder一致)
* 在RecyclerViewDemo1Adapter中实现:
* ViewHolder onCreateViewHolder(ViewGroup parent, int viewType): 映射Item Layout Id,创建VH并返回。
*
* void onBindViewHolder(ViewHolder holder, int position): 为holder设置指定数据。
*
* int getItemCount(): 返回Item的个数。
*
* 可以看出,RecyclerView将ListView中getView()的功能拆分成了onCreateViewHolder()和onBindViewHolder()。
*/
public class RecyclerViewDemo1Adapter extends RecyclerView.Adapter<RecyclerViewDemo1Adapter.ViewHolder> {
private List<String> mData;
public RecyclerViewDemo1Adapter(List<String> data) {
this.mData = data;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater
.from(parent.getContext())
.inflate(R.layout.item_menu_main, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.setData(this.mData.get(position));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//item点击事件
}
});
}
@Override
public int getItemCount() {
return this.mData != null ? this.mData.size() : 0;
}
static class ViewHolder extends RecyclerView.ViewHolder{
private TextView mTextView;
public ViewHolder(View itemView) {
super(itemView);
mTextView = (TextView) itemView.findViewById(R.id.tv_title);
}
public void setData(String title) {
this.mTextView.setText(title);
}
}
}
需要注意的是RecyclerView没有提供如ListView的setOnItemClickListener或者setOnItemLongClickListener之类的Item点击事件,我们必须自己去实现该部分功能,实现的方法有很多种,也比较容易,本例中采用在Adapter中BindViewHolder绑定数据的时候为item设置了点击事件。
小结
RecyclerView的四大组成分别是:
Adapter:为Item提供数据。必须提供,关于Adapter我们上面的代码注释已经说的很明白了
Layout Manager:Item的布局。必须提供,我们需要为RecyclerView指定一个布局管理器
Item Animator:添加、删除Item动画。可选提供,默认是DefaultItemAnimator
Item Decoration:Item之间的Divider。可选提供,默认是空
所以上面代码的运行结果看起来像是是一个没有分割线的ListView
RecyclerView的进阶使用
上面的基本使用我们是会了,而且点击Item也有反应了,不过巨丑无比啊有木有。起码的分割线都没有,真无语
为RecyclerView添加分割线
那么如何创建分割线呢,
创建一个类并继承RecyclerView.ItemDecoration,重写以下两个方法:
onDraw()或者onDrawOver: 绘制分割线。
getItemOffsets(): 设置分割线的宽、高。
然后使用RecyclerView通过addItemDecoration()方法添加item之间的分割线。
RecyclerView的缓存机制
RecyclerView和ListView的回收机制非常相似,但是ListView是以View作为单位进行回收,RecyclerView是以ViewHolder作为单位进行回收。相比于ListView,RecyclerView的回收机制更为完善
源码地址:源码传送门
此致,敬礼
共同学习,写下你的评论
评论加载中...
作者其他优质文章