欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > Android面试总结之Android RecyclerView:从基础机制到缓存优化

Android面试总结之Android RecyclerView:从基础机制到缓存优化

2025/3/31 1:02:31 来源:https://blog.csdn.net/2301_80329517/article/details/146514130  浏览:    关键词:Android面试总结之Android RecyclerView:从基础机制到缓存优化

引言

在 Android 开发中,RecyclerView是高效展示列表数据的核心组件。其强大的性能源于独特的视图复用机制和四级缓存体系。本文将结合源码与示例,带你深入理解RecyclerView的工作原理与优化策略。

核心组件

  • RecyclerView:作为容器视图,负责管理和展示列表数据。它会根据布局管理器对列表项进行布局。
  • LayoutManager:用于确定列表项的布局方式,如线性布局、网格布局、瀑布流布局等。
  • Adapter:充当数据和视图之间的桥梁,负责将数据绑定到视图上。它会创建列表项的视图并填充数据。
  • ViewHolder:用来缓存列表项视图中的子视图,避免每次都通过 findViewById 查找视图,从而提升性能。

工作流程

1. 初始化 RecyclerView

在布局文件里添加 RecyclerView 组件,然后在代码中对其进行初始化。

<androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recyclerView"android:layout_width="match_parent"android:layout_height="match_parent"/>
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;public class MainActivity extends AppCompatActivity {private RecyclerView recyclerView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);recyclerView = findViewById(R.id.recyclerView);// 设置布局管理器recyclerView.setLayoutManager(new LinearLayoutManager(this));}
}
2. 创建 Adapter 和 ViewHolder

Adapter 要继承 RecyclerView.Adapter,并实现必要的方法。ViewHolder 则要继承 RecyclerView.ViewHolder

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {private List<String> dataList;public MyAdapter(List<String> dataList) {this.dataList = dataList;}@NonNull@Overridepublic MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {// 创建视图View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false);return new MyViewHolder(view);}@Overridepublic void onBindViewHolder(@NonNull MyViewHolder holder, int position) {// 绑定数据String data = dataList.get(position);holder.textView.setText(data);}@Overridepublic int getItemCount() {return dataList.size();}public static class MyViewHolder extends RecyclerView.ViewHolder {TextView textView;public MyViewHolder(@NonNull View itemView) {super(itemView);textView = itemView.findViewById(android.R.id.text1);}}
}
3. 设置 Adapter

在 Activity 或者 Fragment 中为 RecyclerView 设置 Adapter

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.List;public class MainActivity extends AppCompatActivity {private RecyclerView recyclerView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);recyclerView = findViewById(R.id.recyclerView);recyclerView.setLayoutManager(new LinearLayoutManager(this));// 模拟数据List<String> dataList = new ArrayList<>();for (int i = 0; i < 100; i++) {dataList.add("Item " + i);}// 设置 AdapterMyAdapter adapter = new MyAdapter(dataList);recyclerView.setAdapter(adapter);}
}

视图复用机制

RecyclerView 最核心的优化点在于视图复用机制。当列表项滑出屏幕时,RecyclerView 不会将其销毁,而是把它放入回收池中。当新的列表项需要显示时,RecyclerView 会优先从回收池中获取可用的视图,然后通过 Adapter 的 onBindViewHolder 方法为其绑定新的数据,这样就避免了频繁创建和销毁视图,大大提升了性能。

RecyclerView 的缓存机制是其高效展示大量数据的关键所在,它能够显著减少视图创建和销毁的开销,从而提升性能和响应速度。下面为你详细介绍 RecyclerView 的缓存机制。

缓存层级

RecyclerView 的缓存机制包含四级缓存,分别是:

  1. Scrap 缓存(mAttachedScrap 和 mChangedScrap)
    • 功能:这是 RecyclerView 的一级缓存,用于临时存储正在被重新布局的 ViewHolder。当 RecyclerView 进行布局操作时,比如滚动、插入或删除项目,这些 ViewHolder 会被暂时从屏幕上移除并放入 Scrap 缓存中,布局完成后再从这里取出重新使用。
    • 特点:速度最快,因为这些 ViewHolder 无需重新绑定数据,可直接复用。
  2. Cache 缓存(mCachedViews)
    • 功能:二级缓存,用于存储最近被移除屏幕的 ViewHolder。当用户快速滚动列表时,这些 ViewHolder 可以被快速复用,而不需要重新创建和绑定数据。
    • 特点:默认大小为 2,可以通过 setItemViewCacheSize 方法进行调整。缓存中的 ViewHolder 保持着原有的数据和状态,复用速度较快。
  3. ViewCacheExtension 缓存
    • 功能:三级缓存,这是一个由开发者自定义的缓存接口。开发者可以根据自身需求实现这个接口,以创建自定义的缓存逻辑。
    • 特点:灵活性高,但需要开发者自己管理缓存的添加、移除和查找操作。
  4. RecycledViewPool 缓存
    • 功能:四级缓存,用于存储不同类型的 ViewHolder。当 Cache 缓存已满时,新移除的 ViewHolder 会被放入 RecycledViewPool 中。当需要新的 ViewHolder 时,如果 Scrap 缓存和 Cache 缓存中没有可用的,就会从 RecycledViewPool 中查找。
    • 特点:这里的 ViewHolder 会被重置,需要重新绑定数据。不同类型的 ViewHolder 可以有不同的缓存大小,默认每个类型的缓存大小为 5。

缓存工作流程

1. 获取 ViewHolder

当 RecyclerView 需要一个新的 ViewHolder 来显示列表项时,会按照以下顺序从缓存中查找:

  • 首先检查 Scrap 缓存,如果找到匹配的 ViewHolder,直接使用,无需重新绑定数据。
  • 若 Scrap 缓存中没有,接着检查 Cache 缓存。如果找到,同样可以直接使用,并且保留原有的数据和状态。
  • 若 Cache 缓存也没有,再检查自定义的 ViewCacheExtension 缓存。
  • 若以上缓存都没有找到,最后检查 RecycledViewPool 缓存。如果找到,需要重新绑定数据。
  • 如果所有缓存中都没有找到合适的 ViewHolder,则调用 Adapter 的 onCreateViewHolder 方法创建一个新的 ViewHolder,并绑定数据。
2. 回收 ViewHolder

当列表项滑出屏幕时,ViewHolder 会按照以下规则被回收:

  • 首先尝试将 ViewHolder 放入 Cache 缓存中。如果 Cache 缓存已满,则将最旧的 ViewHolder 移除,放入 RecycledViewPool 中,然后将新的 ViewHolder 放入 Cache 缓存。
  • 如果 Cache 缓存没有满,直接将 ViewHolder 放入 Cache 缓存。

示例代码

以下是一个简单的示例,展示了如何使用 RecycledViewPool

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.List;public class MainActivity extends AppCompatActivity {private RecyclerView recyclerView1, recyclerView2;private RecyclerView.RecycledViewPool viewPool;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 初始化 RecycledViewPoolviewPool = new RecyclerView.RecycledViewPool();// 第一个 RecyclerViewrecyclerView1 = findViewById(R.id.recyclerView1);recyclerView1.setLayoutManager(new LinearLayoutManager(this));recyclerView1.setRecycledViewPool(viewPool);List<String> dataList1 = new ArrayList<>();for (int i = 0; i < 100; i++) {dataList1.add("Item 1 - " + i);}MyAdapter adapter1 = new MyAdapter(dataList1);recyclerView1.setAdapter(adapter1);// 第二个 RecyclerViewrecyclerView2 = findViewById(R.id.recyclerView2);recyclerView2.setLayoutManager(new LinearLayoutManager(this));recyclerView2.setRecycledViewPool(viewPool);List<String> dataList2 = new ArrayList<>();for (int i = 0; i < 100; i++) {dataList2.add("Item 2 - " + i);}MyAdapter adapter2 = new MyAdapter(dataList2);recyclerView2.setAdapter(adapter2);}
}

在这个示例中,两个 RecyclerView 共享同一个 RecycledViewPool,这样可以提高视图的复用率,减少内存开销。

缓存层级对比

缓存层级存储内容特点典型场景
Scrap 缓存当前屏幕可见 ViewHolder无需重新绑定数据布局更新时复用
Cache 缓存最近移出屏幕的 ViewHolder保留数据状态快速滚动时复用
ViewCacheExtension自定义缓存逻辑开发者可控特殊业务场景
RecycledViewPool未绑定数据的 ViewHolder跨列表共享缓存多个列表复用同一 ViewPool

2. 缓存工作流程

  1. 获取 ViewHolder:按层级依次查找 Scrap → Cache → ViewCacheExtension → RecycledViewPool → 新建
  2. 回收 ViewHolder:移出屏幕时优先存入 Cache,满容后转移至 RecycledViewPool

3. 缓存优化实践

// 配置缓存大小
recyclerView.setItemViewCacheSize(5); // 增大Cache缓存容量
recyclerView.getRecycledViewPool().setMaxRecycledViews(ViewType, 10); // 调整RecycledViewPool容量// 跨列表共享缓存
RecyclerView recyclerView1 = findViewById(R.id.rv1);
RecyclerView recyclerView2 = findViewById(R.id.rv2);
recyclerView2.setRecycledViewPool(recyclerView1.getRecycledViewPool());

性能优化建议

  1. 合理使用 ViewHolder:避免在onBindViewHolder中执行耗时操作
  2. 数据变化优化:使用DiffUtil实现局部刷新
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new MyCallback(oldList, newList));
diffResult.dispatchUpdatesTo(adapter);
  1. 布局优化:减少布局层级,使用merge标签
  2. 预加载策略:通过addOnScrollListener实现分页加载

总结

RecyclerView通过视图复用四级缓存实现了高效的列表渲染,其设计思想对理解现代 UI 框架具有重要参考价值。在实际开发中,需根据业务场景合理配置缓存参数,结合DiffUtil等工具实现性能与体验的平衡。

感谢观看!!!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词