RecyclerView瀑布流优化方案探讨
目录介绍
- 01.规则瀑布流实现
- 02.不规则瀑布流实现
- 2.1 实现方式
- 2.2 遇到问题
- 03.瀑布流上拉加载
- 04.给瀑布流设置分割线
- 05.自定义Manager崩溃
- 06.如何避免刷新抖动
- 07.为何有时出现跳动
- 08.瀑布流图片优化
- 09.onBindViewHolder优化
- 10.瀑布流item点击事件优化
- 11.Glide加载优化
- 12.建议指定图片的宽高
欢迎同行探讨瀑布流极致优化方案
- 如果同行看到这篇文章,有好的瀑布流优化方案,欢迎给出建议,或者给链接也可以。
- 需求:
- 瀑布流大概有10来中不同type的item视图,然后视图是根据动态设置宽高,服务器会返回比例
- 瀑布流中item需要切割圆角
- 目前使用glide加载图片
- 产品说让参考抖音快手类的app,让瀑布流滑动效果特别流畅……但目前遇到问题是滑动十几页没什么问题,但是滑动三四十页的时候会出现卡顿。欢迎同行给出建议!
好消息
- 博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计N篇[近100万字,陆续搬到网上],转载请注明出处,谢谢!
- 链接地址:https://github.com/yangchong211/YCBlogs
- 如果觉得好,可以star一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!
01.规则瀑布流实现
- 最简单规则瀑布流实现,下面这种是设置3列数据,然后组数据高度是相同的。是规则的瀑布流。
02.不规则瀑布流实现
- 最简单的不规则瀑布流实现,下面这种是设置2列数据,然后数据的高度都不同,图片的高度随机。
- 这里是伪代码。假设设置不同高度,代码如下。简单设置不同图片高度不同,这个是在onBindViewHolder中操作。
2.2 遇到问题
- 遇到问题
- 1.RecyclerView 如何实现下拉加载更多;
- 2.StaggeredGridLayoutManager 显示加载更多的时候,加载更多作为最后一个item没有单独占满屏幕宽度,只显示为一个item的宽度;
- 3.StaggeredGridLayoutManager 如何随机设置item的高度;
- 4.StaggeredGridLayoutManager 上拉加载数据刷新UI时,由于高度随机,造成页面item抖动问题;
- 5.RecyclerView莫名的Inconsistency detected崩溃;
- 卡顿和内存释放
- 瀑布流滑动几页感觉还行,但是一旦滑动了三四十页,就感觉页面有些卡顿了。
03.瀑布流上拉加载
- 首先添加监听方法,添加了这个方法就可以上拉加载更多数据呢。但是发现还有点问题,上拉加载更多的那个布局只是占1/spanCount列,这样显得特别难看。那么该如何处理呢,接着往下看……
- 首先要能够监听recyclerView滑动事件;
- 判断recyclerView是否滑动到最后一个item;
- recyclerView 加载更多RecyclerView.Adapter的设置处理:RecyclerView.Adapter的相关代码,主要定义两个ViewHolder类型,footType表示为底部的viewHolder,normalType表示为正常的item的viewHolder,根据position的不同来显示不同的viewholder;
- 因为是瀑布流,要设置footerView占据一行,这个需要这样设置,代码如下所示
04.给瀑布流设置分割线
- 先来看看出现错位,分割线出现问题的代码。下面这种方式根据childCount来判断奇数和偶数设置的不同间距。
- 那么比如说当为奇数时,设置该item到左为20,到右为5;当为偶数时,该item到左为5,到右为20。
- 如果奇数的item都在左边,偶数的item都在右边,那么间距就没有问题。
- 如果第一个item在左边【高度很高】,第2个,第3个,第4个item都在右边,第5个在左边……那么思考一下,这个时候第3个item在右边,那么就会造成间距不规则。
- 显然不能根据奇数或者偶数来设置item左右间距的大小的,会出现错位。
- 解决办法,可以通过StaggeredGridLayoutManager.LayoutParams里的getSpanIndex()来判断,这个方法不管你高度怎样,他都是左右左右开始排列的。
05.自定义Manager崩溃
- RecyclerView莫名的Inconsistency detected崩溃;
- 出现这个异常原因:
- 使用RecyclerView加官方下拉刷新的时候,如果绑定的List对象在更新数据之前进行了clear,而这时用户紧接着迅速上滑RV,就会造成崩溃,而且异常不会报到你的代码上,属于RV内部错误。
- 自定义一个CustomStaggeredGridLayoutManager 在onLayoutChildren对异常进行捕获:
- 出现这个异常原因:
- 关于StaggeredGridLayoutManager异常说明
06.如何避免刷新抖动
- StaggeredGridLayoutManager 上拉加载数据刷新UI时,由于高度随机,造成页面item抖动问题; 这里由于直接调用 notifyDataSetChanged();那么是全局刷新,而刷新的时候item的高度重新随机分配,导致数据刷新的时候会造成抖动。建议采用notifyItemRangeChanged进行局部刷新:
07.为何有时出现跳动
- 由于我们加载的图片高度不确定(宽度确定因为可以根据屏幕宽度和每行Item数目进行等分),而当我们向RecyclerView下方滑动一段距离后,由于ViewHolder的回收机制,item的尺寸并不确定,滑回到上方时Item需要重新自行绘制,于是这个又导致重绘,所以会有闪烁、跳动、空白等问题。说到底,只要我们在重绘前确定了Item的尺寸,那么就可以避免Item去重新计算自己的尺寸,就可以避免重绘导致的诸多问题。
08.瀑布流图片优化
- 具体优化方案
- 第一步:减少布局嵌套,并且在拿到服务器的尺寸后,在onBindViewHolder中给图片控件设置宽高时,避免创建大量临时的LayoutParams对象
- 第二步:使用glide加载,绑定activity或者fragment的生命周期,尽量不用用全局上下文或者静态上下文。注意with()方法中传入的实例会决定Glide加载图片的生命周期,如果传入的是Activity或者Fragment的实例,那么当这个Activity或Fragment被销毁的时候,图片加载也会停止。如果传入的是ApplicationContext,那么只有当应用程序被杀掉的时候,图片加载才会停止。
- 第三步:对于list条目,尤其是瀑布流,不建议使用TransitionOptions来加载设置的动画,尤其是不要使用自己自定义的动画
- 避免使用圆角的ImageView
- 在实际项目内,经常会用到一些带圆角的图片,或者直接就是圆形的图片。圆形的图片,多数用于一些用户的头像之类的显示效果。
- 而在 Android 下,也有大量的类似 XxxImageView 的开源控件,用于操作 Bitmap 以达到一个圆角图片的效果,例如 Github 上比较火的 RoundedImageView。
- 它们大部分的原理,是接收到你传递的 Bitmap ,然后再输出一个与原来 Bitmap 等大的新 Bitmap ,在此基础之上,进行圆角的一些处理,这就导致了,实际上会在内存中,多持有一个 Bitmap ,一下一张图片占用的内存就被加倍了。
- 所以既然已经选择使用Glide,推荐使用glide-transformations这个开源库配合使用,glide-transformations 利用 Glide 的 bitmapTransfrom() 接口,实现对加载的 Bitmap 的进行一些变换操作。glide-transformations提供一系类对加载的图片的变换操作,从形状变换到色彩变换,全部支持,基本上满足大部分开发需要,并且它会复用 Glide 的 BitmapPool ,来达到节约内存的目的。
09.onBindViewHolder优化
- 在这个方法中,主要是做数据绑定到View视图。由于瀑布流会有多种不同type类型的视图,有些需要设置宽高,有的则要从服务器拿到宽高数据然后动态修改视图属性。因此关于宽高的计算其实还可以做一些优化。
- 先来看一下最初的代码,这里只展示动态设置宽高的代码。如下所示
- 看了下面代码,会发现这些问题。第一,频繁计算瀑布流中不同类型的宽度,该宽度是屏幕宽度减去间距,然后是除以2,瀑布流为两行。第二,频繁创建LayoutParams对象,然后设置宽高的属性。
- 然后看一下优化后的代码。
- 那么下面这种代码,就可以极大减少频繁的动态计算宽高等属性。通过imageView34.getLayoutParams()方式获取layoutParams,就可以避免上面那种通过new创建大量的对象。要知道,平时像上面代码那么用也没问题,但是在recyclerView瀑布流中,也可以细微优化一下。
10.瀑布流item点击事件优化
- 关于rv设置item条目点击事件有两种方式:1.在onCreateViewHolder中写;2.在onBindViewHolder中写;3.在ViewHolder中写。那么究竟是哪一种好呢?
- 1.在onCreateViewHolder中写
- 2.在onBindViewHolder中写
- 3.在ViewHolder中写
- 1.在onCreateViewHolder中写
- onBindViewHolder() 中频繁创建新的 onClickListener 实例没有必要,建议实际开发中应该在 onCreateViewHolder() 中每次为新建的 View 设置一次就行。
11.Glide加载优化
- glide优化方案代码,滑动时候禁止加载图片,停止滑动后开始恢复加载图片。
- 绑定控件的生命周期
- 当一个界面离开之后,我们更希望当前的图片取消加载,那么 Glide 是怎么做到的呢?当在recyclerView列表中,item从可见滑动到不可见的时候,如何控制图片请求的生命周期,那么可以与控件生命周期相绑定。
- 低内存的情况下主动清除缓存,看最新版本glide,其实源码中以及处理了下面相关的逻辑。
12.建议指定图片的宽高
- Glide设置图片控件wrap_content不建议支持的问题
- 官方说,不支持并且不建议imageview设置wrap_content。因为这样glide不知道要加载多大的图片给我们才好,在他的接口(Sizes and dimensions)中也有体现。普通的imageview其实也还好,如果放在列表(RecyclerView)中, 由于我们并不知道目标图片大小是多大的,所以我们选择了wrap_content,那么在上下来回滚动过程中,就会导致图片一会大一会小的bug.
- 官方 issue 作者回答如下:
- 所以,如果可以,那么还是指定图片控件的宽高吧!
01.关于博客汇总链接
02.关于我的博客
- github:https://github.com/yangchong211
- 知乎:https://www.zhihu.com/people/yczbj/activities
- 简书:http://www.jianshu.com/u/b7b2c6ed9284
- csdn:http://my.csdn.net/m0_37700275
- 喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
- 开源中国:https://my.oschina.net/zbj1618/blog
- 泡在网上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
- 邮箱:yangchong211@163.com
- 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
- segmentfault头条:https://segmentfault.com/u/xiangjianyu/articles
- 掘金:https://juejin.im/user/5939433efe88c2006afa0c6e
业余demo链接:https://github.com/yangchong211/YCRefreshView
RecyclerView瀑布流优化方案探讨的更多相关文章
- Android瀑布流优化,解决Recyclerview展示大批量图片时Item自动切换、闪烁、空白等问题
本文涉及的代码案例可以在下方的链接中找到,如果对你有帮助,请给个Star(#^.^#) https://github.com/CodeTillDoom/StaggeredRcl 问题分析 这段时间业务 ...
- Dataworks批量刷数优化方案探讨
Dataworks批量刷数优化方案探讨 在数据仓库的日常使用中,经常会有批量补数据,或者逻辑调整后批量重跑数据的场景. 批量刷数的实现方式,因调度工具差异而各有不同. Dataworks调度批量刷数局 ...
- 移动 H5 首屏秒开优化方案探讨
转载bang大神文章,原文<移动 H5 首屏秒开优化方案探讨>,此文仅仅用做自学与分享! 随着移动设备性能不断增强,web 页面的性能体验逐渐变得可以接受,又因为 web 开发模式的诸多好 ...
- Android 解决RecyclerView瀑布流效果结合Glide使用时图片变形的问题
问题描述:使用Glide加载RecyclerView的Item中的图片,RecyclerView使用了瀑布流展示图片,但是滚动时图片会不断的加载,并且大小位置都会改变,造成显示错乱. 解决方法:使用瀑 ...
- 解决RecyclerView瀑布流效果结合Glide使用时图片变形的问题
问题描述:使用Glide加载RecyclerView的Item中的图片,RecyclerView使用了瀑布流展示图片,但是滚动时图片会不断的加载,并且大小位置都会改变,造成显示错乱. 解决方法:使用瀑 ...
- MySQL 大表优化方案探讨
当MySQL单表记录数过大时,增删改查性能都会急剧下降,可以参考以下步骤来优化: 单表优化 除非单表数据未来会一直不断上涨,否则不要一开始就考虑拆分,拆分会带来逻辑.部署.运维的各种复杂度,一般以整型 ...
- Android RecyclerView 瀑布流
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout ...
- Android RecyclerView 瀑布流滑动到最后自动加载更多
mRecycleView.setOnScrollListener(new RecyclerView.OnScrollListener(){ //用来标记是否正在向最后一个滑动,既是否向下滑动 bool ...
- Android Studio [RecyclerView/瀑布流显示]
PuRecyclerViewActivity.java package com.xdw.a122.recyclerview; import android.support.v7.app.AppComp ...
- RecyclerView实例-实现可下拉刷新上拉加载更多并可切换线性流和瀑布流模式(1)
摘要 最近项目有个列表页需要实现线性列表和瀑布流展示的切换,首先我想到的就是上 [RecyclerView],他本身已经很好的提供了三种布局方式,只是简单做个切换应该是很简单的事情,如果要用Recyc ...
随机推荐
- .NET Core开发实战(第14课:自定义配置数据源:低成本实现定制化配置方案)--学习笔记
14 | 自定义配置数据源:低成本实现定制化配置方案 这一节讲解如何定义自己的数据源,来扩展配置框架 扩展步骤 1.实现 IConfigurationSource 2.实现 IConfiguratio ...
- Java连接MySQL8.0样例代码
代码功能: 针对MySQL8.0,可以动态传入数据库连接信息(IP.端口.数据库.用户.密码).以及需要执行查询SQL. 注意:由于代码中打印表中的数据,所以最后在Main方法传入的参数是需要是查询的 ...
- 使用 lspci 和 setpci 调试 PCIe 问题
lspci 命令和 setpci 命令均为 Linux 发行版中原生可用的命令. 这 2 条命令均可提供多级输出,适合在不同时间点用于查看 PCI 总线上训练的不同组件的功能和状态.其中大部分功能均可 ...
- join命令
join命令 join命令用于将两个文件中,指定栏位内容相同的行连接起来.其首先找出两个文件中指定栏位内容相同的行,并加以合并,再输出到标准输出设备. 语法 join [OPTION]... FILE ...
- SSH通道
线下到线上 通过http协议 线上到线下 不能走http,只能通过ssh通道,建立玩ssh通道后,线上线下就可以通道ssh通道进行通信 如:线上为ssm项目 线下为linux项目,二者之间lin ...
- 学习go语言编程之面向对象
类型系统 类型系统是指一个语言的类型体系结构,一个典型的类型系统通常包含如下基本内容: 基础类型,如:byte.int.bool.float等 复合类型,如:数组.结构体.指针等 可以指向任意对象的类 ...
- APISIX介绍
APISIX是什么 Apache APISIX是Apache软件基金会下的云原生API网关,它兼具动态.实时.高性能等特点,提供了负载均衡.动态上游.灰度发布(金丝雀发布).服务熔断.身份认证.可观测 ...
- 第130篇:BOM(window对象)
好家伙,本篇为<JS高级程序设计>第十二章"BOM"学习笔记 什么是BOM? BOM(Browser Object Model) 是指浏览器对象模型,是用于描述这种 ...
- Redis灵魂11问
目录 说说redis都有哪些数据类型吧 Redis为什么快呢? 那为什么Redis6.0之后又改用多线程呢? 知道什么是热key吗?热key问题怎么解决? 什么是缓存击穿.缓存穿透.缓存雪崩? 缓存击 ...
- 【Azure App Services】多次操作App Service伸缩实例遇见限制操作记录
问题描述 多次操作App Services,进行实例数的变化.达到限制后遇见报错: 错误的具体描述为: { "status": "Failed", " ...