尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Android RecyclerView性能优化:Sample项目中的视图回收机制解析

Android RecyclerView性能优化:Sample项目中的视图回收机制解析 Android RecyclerView性能优化Sample项目中的视图回收机制解析【免费下载链接】android-RecyclerViewMigrated:项目地址: https://gitcode.com/gh_mirrors/an/android-RecyclerViewAndroid RecyclerView性能优化核心在于理解视图回收View Recycling机制。本文基于 Google 官方的 android-RecyclerView Sample 示例项目用最小示例带你搞清楚RecyclerView 为什么只需要极少数几个视图就能流畅展示、滚动 60 条乃至百万条数据以及 ViewHolder 在其中扮演了什么角色。一、先认识这个 Sample 项目两种布局、一个回收演示这个项目是 Android 官方的入门级示例包含 Java 与 Kotlin 两套完整实现Java 版Application/src/main/java/com/example/android/recyclerview/Kotlin 版kotlinApp/app/src/main/java/com/example/android/recyclerview/它的功能非常聚焦用 60 条字符串数据This is element #0~#59填充一个列表顶部提供Linear Layout Manager单列线性和Grid Layout Manager双列网格两种布局切换并附带一个实时 Log 面板。下面这张截图来自项目screenshots/目录展示的就是单列线性布局的运行效果——注意顶部 Log 面板里不断刷新的Element 17 set.、Element 18 set.记录这正是视图回收机制正在工作的直接证据二、核心原理ListView 时代为什么不够用了先建立一个直觉假设屏幕一次能显示 8 个条目数据源有 60 条。如果为每一条数据都新建一个视图内存占用和创建开销都会随数据量线性增长——这就是长列表卡顿、OOM 的根源。RecyclerView 的思路完全不同只创建屏幕可见条目 少量缓冲所需的视图当某个条目滑出屏幕时它的视图对象不销毁而是被回收重新绑定给刚滑进来的新条目。项目自身的 README 对这一点有一句最精炼的官方表述见kotlinApp/README.mdRecyclerView can display large datasets that can be scrolled efficiently byrecycling a limited number of views.也就是说60 条数据屏幕上任何时刻真正存在的视图只有个位数。这就是它性能优化的第一性原理。三、ViewHolder Adapter回收机制的两个核心方法回收不是魔法它由 Adapter 的两个回调方法分工完成。核心代码在Application/src/main/java/com/example/android/recyclerview/CustomAdapter.java中1.onCreateViewHolder—— 昂贵的新建操作public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { View v LayoutInflater.from(viewGroup.getContext()) .inflate(R.layout.text_row_item, viewGroup, false); return new ViewHolder(v); }这里执行LayoutInflater.inflate()加载布局、查找子控件开销较大。RecyclerView 只会在视图池不够用时才调用它能省则省。示例中每个条目布局Application/src/main/res/layout/text_row_item.xml就是一个 FrameLayout 一个 TextView 的极简结构——层级越浅inflate 越快这本身就是性能意识。2.onBindViewHolder—— 廉价的换数据操作public void onBindViewHolder(ViewHolder viewHolder, final int position) { Log.d(TAG, Element position set.); viewHolder.getTextView().setText(mDataSet[position]); }回收后的旧视图走到这里不新建只把position对应的新文本贴上去。这个操作应该保持尽可能轻——不要在其中做图片加载、JSON 解析等重活。ViewHolder 的意义它在构造时一次性缓存findViewById的结果见 CustomAdapter.java 第 39-57 行 中ViewHolder内部类避免每次绑定都重复查找控件——这是相对 ListView 旧写法的关键提速点。3.getItemCount告诉 RecyclerView 数据总量示例为 60布局管理器据此规划滚动范围。四、看 Log 日志亲眼验证回收发生了什么这个 Sample 最贴心的设计是把每次onBindViewHolder都写进界面上的 Log 面板日志链路实现在Application/src/main/java/com/example/android/common/logger/LogView.java。仔细看上面的截图Log 里Element 14 set.反复出现在不同批次中。这说明同一个位置乃至同一个视图对象在不同时间点被多次绑定数据——视图被回收、复用、再绑定而不是每滚一条就新建一条。再看另一张截图切换为Grid Layout Manager后的双列网格效果SPAN_COUNT 2同样伴随绑定日志实时滚动五、LayoutManager同一套回收机制不同的排布策略布局逻辑全部由LayoutManager驱动核心代码在Application/src/main/java/com/example/android/recyclerview/RecyclerViewFragment.java的setRecyclerViewLayoutManager()方法第 116-141 行中mLayoutManager new GridLayoutManager(getActivity(), SPAN_COUNT); // 双列网格 // 或 mLayoutManager new LinearLayoutManager(getActivity()); // 单列线性 mRecyclerView.setLayoutManager(mLayoutManager); mRecyclerView.scrollToPosition(scrollPosition);两个值得学习的细节切换布局前先用findFirstCompletelyVisibleItemPosition()记录滚动位置切换后scrollToPosition恢复用户无感知——流畅体验的一部分回收机制与布局无关换成网格布局后视图池的创建/回收逻辑完全不变变的只是排布方式。这体现了 RecyclerView Adapter 管数据绑定、LayoutManager 管排布 的职责分离也是它比 ListView 更灵活的架构基础。六、RecyclerView 性能优化实操清单 结合这个 Sample把可落地的优化要点浓缩如下#优化点在示例中的体现1布局保持扁平行布局仅 1 层 FrameLayout 1 个 TextView2ViewHolder 中缓存控件引用构造时一次findViewById绑定时直接复用3onBindViewHolder只做轻量赋值仅一行setText无任何 IO4视图池自动复用不要手动new View由 RecyclerView 内部按getItemViewType分池管理5切换布局时保持滚动位置先取scrollPosition再恢复6数据更新用精确变更通知实际项目中应配合 DiffUtil 做最小化刷新而非notifyDataSetChanged全量刷新⚠️ 常见反面模式本示例刻意规避了在onBindViewHolder里加载图片、在getViewType逻辑中返回不稳定的类型、为每个条目创建独立 Adapter 实例等都会破坏回收效率。结语RecyclerView 的性能优势本质上是有限视图 回收复用 职责分离三个设计共同作用的结果。通过 android-RecyclerView 这个只有几个文件的 Sample——尤其是CustomAdapter的两个核心回调和那份会暴露绑定行为的 Log 面板——你已经完整看到了回收机制的全貌。把这套心智模型迁移到自己项目中保持绑定轻量、信任视图池、让 LayoutManager 专注排布长列表的流畅体验就水到渠成了。【免费下载链接】android-RecyclerViewMigrated:项目地址: https://gitcode.com/gh_mirrors/an/android-RecyclerView创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表