Android中的RecyclerView

RecyclerView 相当于加强版的 ListView ,比 ListView 更灵活、更高效。

声明依赖项

在 app/build.gradle.kts 中的 dependencies 添加:

1
2
3
dependencies {
implementation("androidx.recyclerview:recyclerview:1.2.1")
}

可将 1.2.1 修改为你想要的版本(一般是最新的稳定版),详情见官方文档

官方文档

点击 Android Studio 右上角的 Sync Project with Gradle Files 同步依赖。

使用方法

MainActivity.kt:

1
2
3
4
5
6
7
8
// 要显示的数据
val data = arrayOf("秦广王", "楚江王", "宋帝王", "仵官王", "阎罗王", "卞城王", "泰山王", "都市王", "平等王", "转轮王")

val recyclerView = findViewById<RecyclerView>(R.id.recycler_view) // 用 id 找到 RecyclerView
recyclerView.layoutManager = LinearLayoutManager(this) // 配置子视图的布局,可切换其他布局,如下一行
// recyclerView.layoutManager = GridLayoutManager(this, 3) // 3表示一行有几个子视图
val recyclerAdapter = MyAdapter(this, description.toMutableList());
recyclerView.adapter = recyclerAdapter

RecyclerViewAdapter.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/// 自定义的 Adapter 类,继承 RecyclerView.Adapter
/// 其中的 RecyclerView.Adapter 是个泛型,需要传入 ViewHolder
/// 在 MyAdapter 类中实现一个自定义的 ViewHolder
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

private final Context context;
public List<String> data;

public MyAdapter(Context context, List<String> data) {
this.context = context;
this.data = data;
}

/// 拿到 RecyclerView 子视图的布局
/// 其中 R.layout.list_item 是配置子视图布局的 xml 文件
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = View.inflate(context, R.layout.list_item, null);
return new MyViewHolder(view);
}

/// 将要显示的数据赋值给子视图
@Override
public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int i) {
myViewHolder.textView.setText(data.get(i));
}

/// 返回 RecyclerView 子视图的数量
@Override
public int getItemCount() {
return data == null ? 0 : data.size();
}

/// 自定义的 ViewHolder ,继承 RecyclerView.ViewHolder
public static class MyViewHolder extends RecyclerView.ViewHolder {

private final TextView textView;

public MyViewHolder(@NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.list_item);
}
}
}

res/layout/list_item.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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="wrap_content"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:orientation="vertical">

<TextView
android:id="@+id/list_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textStyle="bold" />

</LinearLayout>

activity_main.xml:

1
2
3
4
5
6
7
8
9
10
11
12
<?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">

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

</LinearLayout>

<RecyclerView>中加上app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"可以设置其子视图的布局,与 MainActivity.kt 中的

1
recyclerView.layoutManager = LinearLayoutManager(this)

起相同作用。

删除数据并更新

  1. 获取要删除的item的位置position
  2. 从数据源中删除该item
  3. 调用RecyclerView的Adapter的notifyItemRemoved(position)方法通知RecyclerView删除该item
  4. 如果需要更新删除item后的位置,可以调用Adapter的notifyItemRangeChanged(position, itemCount)方法更新
  5. 如果需要撤销删除操作,可以调用Adapter的notifyItemInserted(position)方法插入该item

RecyclerView 与 ListView 的区别

  • 布局不同:ListView只支持垂直方向,而RecyclerView的LayoutManager有横向、竖向、瀑布流、网格等复杂的布局
  • 数据更新:ListView只能刷新全部数据,而RecyclerView支持局部数据刷新
  • 缓存不同:RecyclerView有四级缓存,而ListView只有两级缓存

RecyclerView的四级缓存机制

  1. mChangeScrapmAttachedScrap用来缓存还在屏幕内的ViewHolder
  2. mCachedViews用来缓存移除屏幕之外的ViewHolder,默认上限为2个,即缓存屏幕外2个ViewHolder
  3. mViewCacheExtension自定义的扩展缓存,需要程序员自己实现
  4. RecycledViewPool ViewHolder缓存池,默认上限为5