当前位置: 首页 > news >正文

recyclerview放不同的布局_RecyclerView 性能优化

关于本文的最新勘误,可参见作者的同名博客 RecyclerView 性能优化。


老文一篇,参考 Google 在 Medium 上发表的文章 RecyclerView Prefetch 。RV 是非常成熟的一个框架,GitHub 上有很多基于 RV 的库,大多数都属于 bootstrap 类型,也就是方便管理和使用 RV ;但要提到性能,和裸写并没有什么区别。在编码时注意一些事项更能优化性能。

RV 滑动展示数据的过程,简单可以概括为输入、动画、布局、渲染四个过程,如下图所示,在 Android 5.0 以上具体的渲染过程会交付给 RenderThread(包括阴影的绘制等都由这个线程绘制,而不是 UI Thread ,这也是 5.0 开始图形性能大幅提升的重要原因):

6a6f7c1f2a565f73b9fa3f126b6b5830.png

我们都知道的事实是,滑动展示过程单帧少于 16ms 是 OK 的,超过 16ms 是卡顿的,下图形象地展示了繁重的输入过程会导致卡顿:

0b52a1b798b7f5d57a5c3a693887795c.png

经过分析发现,输入过重的一个重要原因是,展示当前列表项时,同时也在创建下一个新的、没有被缓存的列表项:

5b0399e0c64d0810515911eb0fbf92dd.png

针对这个问题,官方提供的解决方案也很简洁,一次展示过程分别在 UI Thread 和 RenderThread 中完成,两者之间存在顺序关系;由于是不同的线程,线程等待的过程中自然可以利用空闲时间来先把下一次展示过程可以做的先做了,比如创建新的列表项:

7ebc79e2dfee3e42023fd0af9ac287f3.png

开启这样的设置也很简单,只需要升级到 RecyclerView v25.1.0 以上即可,默认提供的 LayoutManager 均提供 prefetch 功能。不过,如果是你自己实现的 LayoutManager 就要自己实现了。具体还请参考这篇博客。

当然想要单纯依靠 prefetch 来保证 RV 滑动不掉帧是不可能的,我们仍然需要将代码中耗时的部分剔除。到这部分和 ListView 的优化就有很多重合的地方了,简化图层结构这些都没什么好说的,推荐大家开始使用 ConstraintLayout;如果存在大量 findViewById(以当前视图为根深度优先遍历)操作,谨慎配合 DataBinding 食用可显著提升获取目标视图的效率。

一个非常常见的问题是,在 ViewHolder 中存在数据处理转换的逻辑:

// 移除字符串中的 HTML 标签,但保留其中的文字
mTextView.setText(Html.fromHtml(data).toString());

Html.fromHtml 这个方法是比较耗时的,对于不同的字符串,几毫秒到十几毫秒不等。就算一次几毫秒,几个 TV 就是十几毫秒,掉帧是十分严重的。这表现出来的一个问题就是,我们真的有必要在 VH 中存在数据处理的逻辑吗?

RV 只是一个视图层级的库,严格意义上来说管理的只是做视图展示的工作;Adapter 和 VH 严格意义上来说做的只是数据与视图的绑定逻辑,而不应该同时做数据的处理逻辑。想象一些我们使用 RV 的一般过程,即从网络异步获取数据到 Adapter notify change ,数据的处理逻辑应该是在 notify change 之前就做好了的,这样在 VH 里就可以简单无压力地做数据与视图的绑定逻辑;同时数据的处理逻辑可以与网络异步线程放在一起,站在用户角度,最多就是网络刷新时间稍长一点。君不见 Twitter 数据结构与视图接口如此复杂,滚动列表时依然流畅,我想一定是做了这方面的处理吧。

相关文章:

  • mq3.8.9版本有什么不同_【SEACMS 8.9版本】从变量覆盖到变量覆盖的SQL注入漏洞
  • matlab中k-means算法_OpenCV图像处理-KMeans 图像处理
  • python中的转义字符是什么意思_python 转义字符、运算符、列表。。。。
  • python发微信公众号消息_个人微信公众号搭建Python实现 -接收和发送消息-基本说明与实现(14.2.1)...
  • python爬虫代写价格_python爬取京东价格
  • lua get reused time_利用redis-lua+python实现接口限流
  • server2008网卡驱动包_网卡工作原理详解
  • svpwm的原理及法则推导和控制算法详解_电机控制要点解疑:SPWM,SVPWM和矢量控制...
  • python删除文件指定字符串,从Python中的字符串中删除特定字符
  • python基础读后感_《python基础教程 》第一章 读书笔记
  • 二叉树的字符图形显示程序_(CSPJ)入门级C++语言试题A卷答案解析阅读程序
  • 服务器显示地址正在使用_用Windows Storage Server 2008做iSCSI存储服务器
  • 权限设计表结构超详细_超详细!!五金模具组件及工程结构设计
  • flex 下对齐_开启 flex 与 grid 布局方式之旅
  • python中的and or的区别_Python 中 (,|)和(and,or)之间的区别
  • Docker入门(二) - Dockerfile
  • Fabric架构演变之路
  • JavaScript DOM 10 - 滚动
  • Joomla 2.x, 3.x useful code cheatsheet
  • leetcode98. Validate Binary Search Tree
  • Markdown 语法简单说明
  • Python十分钟制作属于你自己的个性logo
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • React中的“虫洞”——Context
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • Vue学习第二天
  • 阿里云前端周刊 - 第 26 期
  • 大数据与云计算学习:数据分析(二)
  • 给github项目添加CI badge
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 基于组件的设计工作流与界面抽象
  • 记录:CentOS7.2配置LNMP环境记录
  • 开源地图数据可视化库——mapnik
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 通信类
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • ​学习一下,什么是预包装食品?​
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • #Linux(帮助手册)
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • (145)光线追踪距离场柔和阴影
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (一)基于IDEA的JAVA基础10
  • (转)视频码率,帧率和分辨率的联系与区别
  • (自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载
  • ****Linux下Mysql的安装和配置
  • .net core 连接数据库,通过数据库生成Modell
  • .NET Standard 的管理策略
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .NET 表达式计算:Expression Evaluator
  • .NET 读取 JSON格式的数据
  • .NET开源全面方便的第三方登录组件集合 - MrHuo.OAuth