安卓RecyclerView那些事 - (一)了解RecycleView

转载请附上原博客连接 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的视图,这到底是怎么回事呢?下面我们运行程序,看程序中的打印信息。


安卓RecyclerView那些事 - (一)了解RecycleView_第1张图片
image.png

安卓RecyclerView那些事 - (一)了解RecycleView_第2张图片
image.png

可以看到在第21个item之前都是先调用onCreateViewHolder,再调用onBindViewHolder。之后便只调用了onBindViewHolder。这是应为刚开始RecyclerView没有积累足够的ViewHolder,所以要一直创建。当RecyclerView积累了足够的ViewHolder后,便会复用之前创建的ViewHolder,仅仅调用onBindViewHolder改变ViewHolder中缓存的视图的数据即可,然后将它作为新的item显示出来。这样就不需要为每个item都重新加载一次视图,达到提高性能的目的。
代码已经上传到GitHub
https://github.com/Tiny-Monster/RecycleViewTest1

你可能感兴趣的:(安卓RecyclerView那些事 - (一)了解RecycleView)