Android学习之RecyclerView初探究

•RecyclerView基本用法

  RecyclerView是新增的控件,为了让 RecyclerView 在所有 Android 版本上都能使用;

  Android 团队将 RecyclerView 定义在了 support 库中。

  因此,想要使用 RecyclerView 这个控件,首先需要在项目的 build.gradle 中添加相应的依赖库才行。

  参考我的这篇博客:Android Studio 有关 RecycleView 的使用

  新建一个 Empty Activity,并在 activity_main.xml 中添加如下代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_fruit"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />


</LinearLayout>

  需要注意的是,由于 RecyclerView 并不是内置在系统 SDK 中的,所以需要把完整的包路径写出来。

•为RecyclerView添加适配器

  新建 Fruit 类,代码如下:

public class Fruit {
    private String name;//名称
    private int imgId;//对应图片id

    public Fruit(String name,int imgId){
        this.name = name;
        this.imgId = imgId;
    }

    public String getName() {
        return name;
    }

    public int getImgId() {
        return imgId;
    }
}

  Fruit 类中只有两个字段,name 表示水果名称,imgId 表示水果对应图片的资源 id。

  然后需要为 ListView 的子项指定一个我们自定义的布局;

  在 layout 目录下新建 fruit_item,添加代码如下:

<?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="horizontal"
    android:padding="10dp">
    <!--    注意根布局的 layout_width 和 layout_height 属性的参数
     如果设置成 martch_parent,那么每个列都会占满一个屏幕-->
    <ImageView
        android:id="@+id/fruit_img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/fruit_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:textColor="@color/black"
        android:textSize="20sp" />

</LinearLayout>

  在这个布局中,我们定义了一个 ImageView 用来显示图片,又定义了一个 TextView 用来显示名称。 

  接下来需要创建一个自定义的适配器,这个适配器继承自 RecyclerView.Adapter,并将泛型指定为 FruitAdapter.ViewHolder。

  ViewHolder 是 FruitAdapter 中定义的一个内部类,代码如下:

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

    private List<Fruit> list;///数据源

    /**
     * 首先定义了一个内部类 ViewHolder,继承自 RecyclerView.ViewHolder
     * 然后 ViewHolder 的构造函数中要传入一个 View 参数
     * 这个参数通常就是 RecyclerView 子项的最外层布局(fruit_item.xml)
     * 最后,通过 findViewById() 方法来获取到布局中的 ImageView 和 TextView 的实例
     */
    static class ViewHolder extends RecyclerView.ViewHolder{
        ImageView img;
        TextView name;

        public ViewHolder(@NonNull View view) {
            super(view);
            img = view.findViewById(R.id.fruit_img);
            name = view.findViewById(R.id.fruit_name);
        }
    }

    /**
     *  该方法用于把要展示的数据源传进来,并赋值给变量 list
     *  后续操作都将在这个数据源的基础上进行
     */
    public FruitAdapter(List<Fruit> list){
        this.list = list;
    }

    /**
     *  onCreateViewHolder()方法用于创建 ViewHolder 实例
     *  在这个方法中,将 fruit_item 布局加载进来,然后创建一个 ViewHolder 实例
     *  并把加载出来的布局传入到构造函数中,最后将 ViewHolder 实例返回
     */
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    /**
     *  onBindViewHolder() 方法用于对RecyclerView 子项的数据进行赋值
     *  会在每个子项被滚动到屏幕内的时候执行
     *  这里通过 position 参数得到当前项的 Fruit 实例
     *  然后再将数据设置到 ViewHolder 的 ImageView 和 TextView 当中
     */
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Fruit fruit = list.get(position);
        holder.img.setImageResource(fruit.getImgId());
        holder.name.setText(fruit.getName());
    }

    /**
     *  返回数据源的长度
     *  用来告诉 RecyclerView 一共有多少子项
     */
    @Override
    public int getItemCount() {
        return list.size();
    }
}

 说明

  虽然这段代码看上去有点长,但其实他比 ListView 的适配器🔗要更容易理解;

  这里首先,我们定义了一个内部类 ViewHolder,ViewHolder 要继承自 RecyclerView.ViewHolder。

  然后,ViewHolder 的构造函数中要传入一个 View 参数,这个参数通常就是 RecyclerView 子项的最外层布局;

  那么,我们可以通过  findViewById() 方法来获取到布局中的  ImageView 和 TextView 的实例了。

  接着往下看,FruitAdapter 中也有一个构造函数;

  这个方法用于把要展示的数据传进来,并赋值给一个全局变量 list,我们后续的操作都将在这个数据源上进行。

  继续往下看,由于 FruitAdapter 继承自 RecyclerView.Adapter;

  那么就必须重写  onCreateViewHolder() , onBindViewHolder() 和 getItemCount() ;

  •  onCreateViewHolder() 方法是用于创建 ViewHolder 实例的

    • 在这个方法中,将 fruit_item 布局动态加载进来🔗
    • 然后创建一个 ViewHolder 实例,并把加载出来的布局传入到构造函数中
    • 最后将 ViewHolder 的实例返回
  •  onBindViewHolder() 方法是用于对 RecyclerView 子项的数据进行赋值的

    • 会在每个子项被滚动到屏幕内的时候执行
    • 这里我们通过 positon 参数得到当前项的 Fruit 实例,然后再将数据设置到 ViewHolder 的 ImageView 和 TextView 中
    • Bind 的字面意思就是捆绑,这个方法我们也可以理解成将数据与布局捆绑在一起
    • fruit.getImgId() <-> holder.img
    • fruit.getName() <-> holder.name
  •  getItemCount() 方法用于告诉 RecyclerView 一共有多少子项

    • 直接返回数据源的长度就可以了

  适配器准备好了之后,就可以开始使用 RecyclerView 了,修改 MainActivity 中的代码,如下所示:

public class MainActivity extends AppCompatActivity {

    private RecyclerView rv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        rv = findViewById(R.id.rv_fruit);

        /*LayoutManager 用于指定 RecyclerView 的布局方式
           这里使用的 LinearLayoutManager 是线性布局
           可以实现和 ListView 类似的效果*/
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        rv.setLayoutManager(layoutManager);

        FruitAdapter adapter = new FruitAdapter(getData());
        rv.setAdapter(adapter);
    }

    private List<Fruit> getData() {
        List<Fruit> list = new ArrayList<>();

        list.add(new Fruit("apple", R.drawable.apple));
        list.add(new Fruit("banana", R.drawable.banana));
        list.add(new Fruit("oranges", R.drawable.oranges));

        return list;
    }

}

 

•运行效果

  

 

posted @ 2021-01-27 20:51  MElephant  阅读(204)  评论(0编辑  收藏  举报