什么是 RecyclerView?想象你在翻看一本很厚的相册:
你的眼睛一次只能看到当前打开的这一页(屏幕可见区域)
翻页时,你看到新的照片,之前的照片就看不到了(视图回收)
你不需要一次性把所有照片都拿出来(内存优化)RecyclerView 就是这样工作的:
只创建屏幕可见数量的 item 视图
当用户滑动时,复用已有的视图,只更新显示的数据
这样就能节省大量内存,提高性能
2️⃣ 基础概念解析
2.1 三大核心组件
1.Adapter(适配器)
就像一个服务员,负责:
准备菜单(创建视图)
上菜(绑定数据到视图)
记录有多少道菜(数据总数)
2.ViewHolder(视图持有者)
像是一个托盘,用来盛放视图组件
避免重复 findViewById,提高性能
3.LayoutManager(布局管理器)
像是餐厅的桌子摆放方式:
直线排列(LinearLayoutManager)
网格排列(GridLayoutManager)
错落排列(StaggeredGridLayoutManager)
3️⃣ 实际代码示例(以相册为例)
3.1 首先,定义每个 item 的布局(item_photo.xml):
xml version="1.0" encoding="utf-8"?>
android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp"> android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> android:id="@+id/imageView" android:layout_width="match_parent" android:layout_height="200dp" android:scaleType="centerCrop"/> android:id="@+id/textDescription" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp"/> LinearLayout> androidx.cardview.widget.CardView> 3.2 创建 ViewHolder(定义托盘): // ViewHolder 就像托盘,用来存放 item 中的各个视图组件 class PhotoViewHolder extends RecyclerView.ViewHolder { // 声明需要操作的视图组件 ImageView imageView; // 照片 TextView textDescription; // 描述文字 // 构造方法,找到所有需要的视图组件 PhotoViewHolder(@NonNull View itemView) { super(itemView); // 初始化视图组件,找到对应的视图 imageView = itemView.findViewById(R.id.imageView); textDescription = itemView.findViewById(R.id.textDescription); } } 3.3 创建 Adapter(适配器): class PhotoAdapter extends RecyclerView.Adapter // 数据源 private List // 构造方法,传入数据 PhotoAdapter(List this.photoList = photoList; } // 1. 创建新的 ViewHolder(准备新的托盘) @Override public PhotoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // 将 XML 布局文件转换为视图对象 View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_photo, parent, false); // 创建并返回 ViewHolder return new PhotoViewHolder(view); } // 2. 绑定数据到 ViewHolder(将数据放到托盘上) @Override public void onBindViewHolder(PhotoViewHolder holder, int position) { // 获取当前位置的数据 PhotoItem photo = photoList.get(position); // 设置图片 Glide.with(holder.imageView) .load(photo.getImageUrl()) .into(holder.imageView); // 设置描述文字 holder.textDescription.setText(photo.getDescription()); // 设置点击事件 holder.itemView.setOnClickListener(v -> { // 处理点击事件,比如跳转到详情页 Intent intent = new Intent(v.getContext(), PhotoDetailActivity.class); intent.putExtra("photo_url", photo.getImageUrl()); v.getContext().startActivity(intent); }); } // 3. 返回数据总数(告诉系统有多少个 item) @Override public int getItemCount() { return photoList.size(); } } 3.4 在 Activity 中使用: public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; private PhotoAdapter adapter; private List @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 1. 初始化数据 photoList = new ArrayList<>(); // 添加一些测试数据 photoList.add(new PhotoItem("图片1", "这是第一张图片")); photoList.add(new PhotoItem("图片2", "这是第二张图片")); // 2. 找到 RecyclerView recyclerView = findViewById(R.id.recyclerView); // 3. 创建适配器 adapter = new PhotoAdapter(photoList); // 4. 设置布局管理器(决定如何排列 item) recyclerView.setLayoutManager(new GridLayoutManager(this, 2)); // 2列网格布局 // 5. 设置适配器 recyclerView.setAdapter(adapter); } } 4️⃣ 常用操作 4.1 添加新数据: // 添加一条新数据 PhotoItem newPhoto = new PhotoItem("新图片", "新描述"); photoList.add(newPhoto); // 通知适配器在末尾添加了一条数据 adapter.notifyItemInserted(photoList.size() - 1); 4.2 删除数据: // 删除指定位置的数据 photoList.remove(position); // 通知适配器数据已删除 adapter.notifyItemRemoved(position); 4.3 更新数据: // 更新指定位置的数据 photoList.get(position).setDescription("新的描述"); // 通知适配器数据已更改 adapter.notifyItemChanged(position); 5️⃣ 布局管理器详解 5.1 线性布局(LinearLayoutManager): // 垂直列表 recyclerView.setLayoutManager(new LinearLayoutManager(this)); // 水平列表 recyclerView.setLayoutManager( new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false) ); 5.2 网格布局(GridLayoutManager): // 2列网格 recyclerView.setLayoutManager(new GridLayoutManager(this, 2)); // 3列网格 recyclerView.setLayoutManager(new GridLayoutManager(this, 3)); 5.3 瀑布流布局(StaggeredGridLayoutManager): // 2列瀑布流 recyclerView.setLayoutManager( new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL) ); 6️⃣ 优化技巧 1.设置固定大小: // 如果列表项的大小是固定的,设置这个可以提高性能 recyclerView.setHasFixedSize(true); 2.添加分割线: // 添加简单的分割线 DividerItemDecoration divider = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL); recyclerView.addItemDecoration(divider); 3.设置点击事件: // 在 ViewHolder 中设置点击事件 holder.itemView.setOnClickListener(v -> { int position = holder.getAdapterPosition(); PhotoItem photo = photoList.get(position); // 处理点击事件 Toast.makeText(v.getContext(), "点击了: " + photo.getDescription(), Toast.LENGTH_SHORT).show(); }); 7️⃣ 常见问题解答 1.为什么要使用 ViewHolder? 避免重复 findViewById,提高性能 方便管理每个 item 的视图组件 Android 强制要求使用 ViewHolder 模式 2.如何处理点击事件? 可以在 ViewHolder 中设置 可以通过接口回调到 Activity 中处理 可以直接在 onBindViewHolder 中设置 3.数据更新为什么要调用 notify 方法? 通知 RecyclerView 数据发生了变化 RecyclerView 才知道需要刷新界面 不同的 notify 方法有不同的刷新效果