ListView 与 RecyclerView 你应该弄懂的都在这里了

·  阅读 1181

ListView 相关

ListView 是什么?(上古神器)不,是不是该问 RecyclerView 是什么?(也是上古神器?在它的替代品出来之前最好别这样称呼)趁着这段时间,我想我也应该把这些乱七八糟的东西整理一下。

OK,不演了,ListView 和 RecyclerView 都是用来展示列表数据了。相比与 ListView ,RecyclerView 更加强大,下面先说 ListView。

ListView 适配器

关于 ListView 先简单看一下它的适配器代码:

public class ListViewAdapter extends BaseAdapter {

    //用于加载 item
    private LayoutInflater mInflater;
    //通过构造函数 把 Context 传递进来
    public ListViewAdapter(Context context) {
        mInflater = LayoutInflater.from(context);
    }

    /**
     * 获取的数据存储在这个集合中,一般来说这个集合中存储了子项的 item
     */
    private List mList = new ArrayList();

    /**
     * @return 返回集合的大小
     */
    @Override
    public int getCount() {
        return mList.size();
    }

    /**
     * @param position
     * @return 返回具体的 item
     */
    @Override
    public Object getItem(int position) {
        return mList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    /**
     * 作用:加载 子项 item 的布局
     *
     * @param position    item 的位置
     * @param convertView item 进行复用,避免一个 item 发生多次加载的情况
     * @param parent      父容器,根据具体的情况而定
     * @return item
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null){
            convertView = mInflater.inflate(R.layout.activity_detail,parent,false);
        }
        //对 item 进行复用,返回 convertView
        return convertView;
    }
}
复制代码

ListView 的优化

可以看到,基本上每一个 item 都需要在 getView() 中加载,如果 item 的数量过多,就会产生性能问题,影响用户体验。这个时候我们就需要使用 ViewHolder(开发者自定义类),这是 ListViewAdapter 的内部类,它的代码如下:

    /**
     * 作用:加载 子项 item 的布局
     *
     * @param position    item 的位置
     * @param convertView item 进行复用,避免一个 item 发生多次加载的情况
     * @param parent      父容器,根据具体的情况而定
     * @return item
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null){
            holder = new ViewHolder();
            convertView = mInflater.inflate(R.layout.activity_detail,parent,false);
            convertView.setTag(holder);
        } else {
        	如果 convertView 不为空,直接进行复用
            holder = (ViewHolder) convertView.getTag();
        }
        //对 item 进行复用,返回 convertView
        return convertView;
    }
	//这是一个内部类
    private class ViewHolder{
        //获取 item 的控件都定义在这里
    }
复制代码

好了,关于 ListView 就到这里了,下面总结两个关键点:

  • 自定义 ListViewAdapter ,继承 BaseAdapter。
  • 自定义 ViewHolder 和 convertView 一起完成复用优化工作。

RecyclerView 相关

下面开始写 RecyclerView ,先把 RecyclerView 的关键点总结在这里。其实和 ListView 是差不多的,主要有两条:

  • RecyclerViewAdapter 继承 Recyclerview.Adapter ,其内部类 ViewHolder 继承 RecyclerView.ViewHolder。
  • 设置布局管理器,控制布局效果

RecyclerView 适配器

先看下面 RecyclerView 适配器的代码:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {

    /**
     * 这个方法主要生成为每个Item inflater出一个View,但是该方法返回的是一个ViewHolder。
     * 该方法把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例,
     * 当然这个ViewHolder需要我们自己去编写。
     *
     * @param parent
     * @param viewType
     * @return viewHolder
     */
    @NonNull
    @Override
    public RecyclerViewAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return null;
    }

    /**
     * 这个方法主要用于适配渲染数据到View中,
     * 方法提供给你了一viewHolder而不是原来的convertView
     *
     * @param holder
     * @param position
     */
    @Override
    public void onBindViewHolder(@NonNull RecyclerViewAdapter.ViewHolder holder, int position) {
        //在这里更新 UI
    }

    /**
     * @return 返回 item 的数量
     */
    @Override
    public int getItemCount() {
        return 0;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
        }
    }
}
复制代码

从基础使用上看,我们明显可以看出,RecyclerView 相比 ListView 在基础使用上的区别主要有如下几点:

  • ViewHolder 的编写规范化了。
  • RecyclerView 复用 item 的工作 Google 全帮你搞定了,不需要再像 ListView 那样自己调用 setTag()。
  • RecyclerView 需要设置 KayoutManager

如何在 Activity 中使用 RecyclerView

接下来看一下如何在 Activity 中使用 RecyclerView :(ListView 大致相同)

        //1、设置布局管理器
        LinearLayoutManager manager = new LinearLayoutManager(this);
        RecyclerView recyclerView = findViewById(R.id.detail_rv);
        recyclerView.setLayoutManager(manager);
        //2、设置适配器
        RecyclerViewAdapter adapter = new RecyclerViewAdapter();
        recyclerView.setAdapter(adapter);
复制代码

RecyclerView 的布局管理器

关于 RecyclerView ,还得再说一下它的布局管理器,RecyclerView 提供了三种布局管理器可供选择:

  • LinerLayoutManager 以垂直或者水平列表方式展示
  • GridLayoutManager 以网格方式展示item
  • StaggeredGridLayoutManager 以瀑布流方式展示Item

之所以说 RecyclerView 更加强大,也正是因为 RecyclerView 提供了多种布局管理器,只需在 Activity 中进行设置即可。另外,关于布局管理器的一些API如下:

    canScrollHorizontally();//能否横向滚动
    canScrollVertically();//能否纵向滚动
    scrollToPosition(int position);//滚动到指定位置

    setOrientation(int orientation);//设置滚动的方向
    getOrientation();//获取滚动方向

    findViewByPosition(int position);//获取指定位置的Item View
    findFirstCompletelyVisibleItemPosition();//获取第一个完全可见的Item位置
    findFirstVisibleItemPosition();//获取第一个可见Item的位置
    findLastCompletelyVisibleItemPosition();//获取最后一个完全可见的Item位置
    findLastVisibleItemPosition();//获取最后一个可见Item的位置
复制代码

RecyclerView 的分割线

我们可以为 REcyclerview 的 item 绘制分割线,用系统已经定义好的分割线:

//添加分割线
myRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
复制代码

同样,我们也可以定义自己的分割线,实现不同的效果:

自定义间隔样式需要继承RecyclerView.ItemDecoration类,该类是个抽象类,官方目前并没有提供默认的实现类,主要有三个方法。

  • onDraw(Canvas c, RecyclerView parent, State state),在Item绘制之前被调用,该方法主要用于绘制间隔样式。
  • onDrawOver(Canvas c, RecyclerView parent, State state),在Item绘制之前被调用,该方法主要用于绘制间隔样式。
  • getItemOffsets(Rect outRect, View view, RecyclerView parent, State state),设置item的偏移量,偏移的部分用于填充间隔样式,即设置分割线的宽、高;在RecyclerView的onMesure()中会调用该方法
分类:
Android
标签:
分类:
Android
标签:
收藏成功!
已添加到「」, 点击更改