转载请附上原博客连接 https://www.jianshu.com/p/69ac902e688c
项目里面需要一个下拉刷新,上滑到底部加载更多的RecyclerView,所以最近又回顾了一下之前的知识,有了一些更深的理解。
RecyclerView的优点
RecyclerView相对于ListView有很多好处,比如:
1.相对于ListView,RecyclerView的效率更高,更符合设计模式。
在ListView中,如果我们不去优化Adapter.getView(int position, View convertView,ViewGroup parent)方法时,每个item滚动到屏幕可见区域时,ListView都会调用Adapter的getView()方法重新加载一下item的布局,这样性能上有很大的损失。通常我们优化ListView是用如下的方法
public class MyAdapter extends ArrayAdapter{
private List myDataList = new ArrayList<>();
public MyAdapter(@NonNull Context context, int resource) {
super(context, resource);
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
data myData = myDataList.get(position);
View view;
ViewHolder viewHolder;
if(convertView==null){
view= LayoutInflater.from(getContext()).inflate(R.layout.list_item,parent,false);
viewHolder=new ViewHolder();
viewHolder.msg=(TextView)view.findViewById(R.id.msg);
view.setTag(viewHolder);
}else{
view=convertView;
viewHolder=(ViewHolder) view.getTag();
}
viewHolder.msg.setText(myData.getMsg());
return view;
}
class ViewHolder{
TextView msg;
}
}
就是我们将item的所有子view缓存在ViewHolder中,并将ViewHolder放入convertView的Tag中。这样在getView的时候我们先判断是否缓存了子view,如果没有缓存,我们在去加载子view。
而在RecyclerView中,RecyclerView自动帮我们完成了View的缓存,创建和数据绑定,我们只需要告诉RecyclerView怎么创建View和绑定数据就行。
2.相对于ListView,RecyclerView更加美观
在RecyclerView中,系统已经为我们定义好了许多,比如:线性布局,网格布局,瀑布布局等。还可以定义滑动的方向,你可以快速地设置横向滑动或者竖向滑动,这些都是ListView没有的。
3.子项的点击
在ListView中为我们预置了点击事件的接口setOnItemClickListener(),不过这个点击事件是整个Item的点击,他是覆盖在item中所有子控件之上的,要为想为item中的每个控件添加点击事件,ListView是比较麻烦的。而RecyclerView中虽然没有为我们预置点击事件,但是我们可以灵活地为item中每个子控件添加点击之间,操作更加精确。
4.可以添加动画
可以控制Item增删的动画,通过ItemAnimator这个类进行控制。
总之,RecyclerView的功能是比ListView强大许多的。
RecyclerView的基本使用方法
1.创建item布局
示例如下
2.创建ViewHolder
ViewHolder的作用就是保存对item的左右子view的引用,用以缓存视图,不用每次都重新创建
public class ViewHolder extends RecyclerView.ViewHolder{
TextView msg;//保持textView的引用,作为缓存
public ViewHolder(View itemView) {
super(itemView);
msg=(TextView)itemView.findViewById(R.id.msg);
}
}
3.创建Adapter
Adapter是RecyclerView和ViewHolder之前的桥梁。RecyclerView的每一个item被滚动到屏幕上显示的时候,首先会调用Adapter的getItemCount获得item数量,然后调用onCreateViewHolder来创建视图(并不是没一个item都需要调用onCreateViewHolder,当RecyclerView创建足够多的ViewHolder后,就会复用之前已经创建的ViewHolder,从而提高性能,这一点下面我会进行验证),获得ViewHolder中保存的视图后,最后调用onBindViewHolder为视图绑定数据和事件。这样,一个item就可以显示出来了。Adapter的代码如下
public class RecyclerAdapter extends RecyclerView.Adapter{
private static final String TAG= "RecyclerAdapter";
public Context context;
public List dataList=new ArrayList<>();
public data mData;
private TextClickListener clickListener;
public RecyclerAdapter(Context context,List dataList){
this.context=context;
this.dataList=dataList;
}
/**
* 创建viewholder
* @param parent
* @param viewType
* @return
*/
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View item = LayoutInflater.from(context).inflate(R.layout.recycleview_item,parent,false);
Log.e(TAG,"onCreateViewHolder");
return new ViewHolder(item);
}
/**
* 绑定数据
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
mData=dataList.get(position);
((ViewHolder) holder).msg.setText(mData.getMsg());
if(clickListener!=null){
((ViewHolder) holder).msg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
clickListener.OnClick(((ViewHolder) holder).msg,position);
}
});
}
Log.e(TAG,"onBindViewHolder:"+mData.getMsg());
}
@Override
public int getItemCount() {
return dataList.size();
}
public void setClickListener(TextClickListener clickListener){
this.clickListener=clickListener;
}
}
4.使用RecyclerView
在页面布局用引入RecyclerView
在Activity中使用RecyclerView
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
RecyclerAdapter recyclerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView)findViewById(R.id.recyclerView);
recyclerAdapter = new RecyclerAdapter(MainActivity.this,data.getDataList());
recyclerAdapter.setClickListener(new TextClickListener() {
@Override
public void OnClick(View view, int position) {
Toast.makeText(MainActivity.this,"点击了第"+position+"个item",Toast.LENGTH_SHORT).show();
}
});
recyclerView.setAdapter(recyclerAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
}
}
Adapter中onCreateViewHolder和onBindViewHolder的调用顺序
我们知道ViewHolder中保存了item中的控件的引用,用来缓存item中的控件视图。onCreateViewHolder是创建ViewHolder的,也就是创建item中的控件视图的。onBindViewHolder是为缓存的控件绑定数据的。我们说RecyclerView比ListView的性能更高,是应为RecyclerView重复使用了item的视图,这到底是怎么回事呢?下面我们运行程序,看程序中的打印信息。
可以看到在第21个item之前都是先调用onCreateViewHolder,再调用onBindViewHolder。之后便只调用了onBindViewHolder。这是应为刚开始RecyclerView没有积累足够的ViewHolder,所以要一直创建。当RecyclerView积累了足够的ViewHolder后,便会复用之前创建的ViewHolder,仅仅调用onBindViewHolder改变ViewHolder中缓存的视图的数据即可,然后将它作为新的item显示出来。这样就不需要为每个item都重新加载一次视图,达到提高性能的目的。
代码已经上传到GitHub
https://github.com/Tiny-Monster/RecycleViewTest1