RecycleView局部刷新闪动的问题

2023-11-05 02:10

本文主要是介绍RecycleView局部刷新闪动的问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

腾讯老司机的RecyclerView局部刷新爬坑之路

转载 2016年10月21日 16:15:18
  • 2671
  • 编辑
  • 删除



作者:Hoolly,腾讯移动客户端开发工程师。 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处
WeTest导读安卓开发者都知道,RecyclerView比ListView要灵活的多,但不可否认的里面的坑也同样埋了不少人。下面让我们看看腾讯开发工程师用实例讲解自己踩坑时的解决方案和心路历程。 话说有图有真相,首先来对比一下局部刷新前后的效果:

优化之前的效果:



优化之后的效果:


可以看到,优化之后,列表中的这张大图不在有一闪一闪亮晶晶的效果了!

那么,这是如何做到的呢?这是本文的重点,本文的大纲主要包括:
  1. 分析为什么会闪一下

  2. 对分析的可能造成闪动的问题进行解决

  3. 验证是否解决


一、为什么会闪一下?

我们的需求是大家已经看到了,点击打分,弹出一个对话框,点击一个分数,这时候,通过一些列复杂的转换(当然不是本文的论述的重点),这时候到了要更新列表项了,如是很自然,我们会这么做:


因为,操作的那个列表项你是知道他的position,所以你可以这么做,(当然,我之前是直接notifyDataSetChanged的,这个会照成所以不不要的item也会刷新)然而,闪动还是出现了,那么我开始怀疑:
  1. 流传甚为广泛的一种说法,imageView的宽高不固定导致的(wrap_content)?

  2. 这个是RecyclerView自带的更新动画效果导致的?

  3. 这个是因为图片加载框架(glide 的 animte)的动画效果导致的?

  4. getView中(RecyclerView中是onBindViewHolder)加载图片的时候,设置一个tag,当发现这个imageView的tag和之前的tag一致时就不加载



二、带着思考,就去尝试吧!

1、对于第一种,我的做法是自己写了一个自定义的imageView,重写omMeasure方法,如下:


因为我们的这个列表项中的图片是(高=宽)的,因此,我才这么写,这样写也有一个好处,不用在onBindViewHolder中去动态的计算出高度,然后在已layoutParm的方式设置给imageView,相信不少小伙伴都做过了吧!

然而,遗憾的是,他并没有解决闪一下的问题!此时这个闪动的原因显然不在这里,但是这里做的,可以保留下来。


2、对于第二种说法,我参考了这里 http://stackoverflow.com/questions/29331075/recyclerview-blinking-after-notifydatasetchanged

的做法:


以及也尝试了这种


然而,那种渐变的闪动消失了,但是,取而代之的是一种更加不可接受的闪动,这里就不用gif展示了,因此原因也并不在此处。


3、对于对三种说法,我也去尝试了一下将glide加载改为:


然而得到的依然是一个失望的结果,依然没有解决闪动的问题,原因也不在此处。


4、那么,就剩下最后一个猜测了,那么会不会是它呢?那就试试吧,于是代码改为:


这里的做法其实就是设置Tag,那么是骡子是马,拉出来溜溜吧,结果更加令人发指,如图:


好吧,此时已经有点崩溃了,显然这个也不是我要的结果,那么此时是否应该在静下来想一想,自己对于可能的几种原因做过的一些对策,是否有哪里遗漏了。经过思考,发现并没有!!那么一定是还有其他的原因,没有考虑到!

还是去翻一翻RecyclerView的api吧,我注意到了这个api:



可以看到这里有一个payload的参数,use null to identify a “full” update这是说如果传null就是全部更新,回过头去看一看我们之前的调用方式:

看一下源码,发现


实际上,payload这个参数就是传的null,那也就是说如果传一个不为null的参数,就可以对列表项中的具体控件更新了?

http://stackoverflow.com/questions/33176336/need-an-example-about-recyclerview-adapter-notifyitemchangedint-position-objec

我了解到这个方法的使用方式是这样的:


然来,onBindViewHolder有这么一个重载方式,如是我也这么做了,在下面这个重载中,去更新我想更新的控件:


然后,更新的方式变成了这种:


是骡子是马,那就在遛一遛吧!

然而,依然是会闪一下!!!这这么会!!!还是调试一下吧,新重载onBindViewHolder方法有没有被执行,一更代码,发现果然没有被执行! 那么,究竟是什么鬼?去网上查了一下,有人给出了一个解决办法:

http://stackoverflow.com/questions/32463136/recyclerview-adapter-notifyitemchanged-never-passes-payload-to-onbindviewholde


需要重写这个动画,让永远返回true,已达到newHolder和olderHolder是同一个,然而,这真的就是我的救命稻草吗?


那么,是骡子是马,拉出来溜溜吧,然而,并不是马!!进源码看一看


发现其实只要我们传入的payload不为空,那么返回的就是true?重写有意义吗?显然,我重载的onBindViewHolder方法并没有执行的原因显然不是这个。

那么,到底,到底问题出在何处?会不会是XrecyclerView的问题?根据调用栈,我看到第一个onBindViewHolder被执行了,往上面跟,发现XrecyclerView的实现果然存在问题!



如图,作者仅仅只实现了,不带payload的方法,最后adapter调用的只有不带paylaod的方法!所以,重写一个吧!


最后!终于达到了想要的效果了,经过这次爬坑,选择一个开源的框架真滴是需要慎重再慎重。

总结

实际上RecyclerView做局部刷新是非常容易的,其实就是使用好带payload参数的这个notifyItemRangeChanged方法,以及override带payload的这个onBindViewHolder方法,在onBindViewHolder中去刷新你想更新的控件即可,并非是网上传闻的那些原因,当然此处爬坑时间之长,也可能更选用开源控件不当有关,所以,选择开源控件,要谨慎再谨慎!


作者:Hoolly,腾讯移动客户端开发工程师。 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处
WeTest导读安卓开发者都知道,RecyclerView比ListView要灵活的多,但不可否认的里面的坑也同样埋了不少人。下面让我们看看腾讯开发工程师用实例讲解自己踩坑时的解决方案和心路历程。 话说有图有真相,首先来对比一下局部刷新前后的效果:

优化之前的效果:



优化之后的效果:


可以看到,优化之后,列表中的这张大图不在有一闪一闪亮晶晶的效果了!

那么,这是如何做到的呢?这是本文的重点,本文的大纲主要包括:
  1. 分析为什么会闪一下

  2. 对分析的可能造成闪动的问题进行解决

  3. 验证是否解决


一、为什么会闪一下?

我们的需求是大家已经看到了,点击打分,弹出一个对话框,点击一个分数,这时候,通过一些列复杂的转换(当然不是本文的论述的重点),这时候到了要更新列表项了,如是很自然,我们会这么做:


因为,操作的那个列表项你是知道他的position,所以你可以这么做,(当然,我之前是直接notifyDataSetChanged的,这个会照成所以不不要的item也会刷新)然而,闪动还是出现了,那么我开始怀疑:
  1. 流传甚为广泛的一种说法,imageView的宽高不固定导致的(wrap_content)?

  2. 这个是RecyclerView自带的更新动画效果导致的?

  3. 这个是因为图片加载框架(glide 的 animte)的动画效果导致的?

  4. getView中(RecyclerView中是onBindViewHolder)加载图片的时候,设置一个tag,当发现这个imageView的tag和之前的tag一致时就不加载



二、带着思考,就去尝试吧!

1、对于第一种,我的做法是自己写了一个自定义的imageView,重写omMeasure方法,如下:


因为我们的这个列表项中的图片是(高=宽)的,因此,我才这么写,这样写也有一个好处,不用在onBindViewHolder中去动态的计算出高度,然后在已layoutParm的方式设置给imageView,相信不少小伙伴都做过了吧!

然而,遗憾的是,他并没有解决闪一下的问题!此时这个闪动的原因显然不在这里,但是这里做的,可以保留下来。


2、对于第二种说法,我参考了这里 http://stackoverflow.com/questions/29331075/recyclerview-blinking-after-notifydatasetchanged

的做法:


以及也尝试了这种


然而,那种渐变的闪动消失了,但是,取而代之的是一种更加不可接受的闪动,这里就不用gif展示了,因此原因也并不在此处。


3、对于对三种说法,我也去尝试了一下将glide加载改为:


然而得到的依然是一个失望的结果,依然没有解决闪动的问题,原因也不在此处。


4、那么,就剩下最后一个猜测了,那么会不会是它呢?那就试试吧,于是代码改为:


这里的做法其实就是设置Tag,那么是骡子是马,拉出来溜溜吧,结果更加令人发指,如图:


好吧,此时已经有点崩溃了,显然这个也不是我要的结果,那么此时是否应该在静下来想一想,自己对于可能的几种原因做过的一些对策,是否有哪里遗漏了。经过思考,发现并没有!!那么一定是还有其他的原因,没有考虑到!

还是去翻一翻RecyclerView的api吧,我注意到了这个api:



可以看到这里有一个payload的参数,use null to identify a “full” update这是说如果传null就是全部更新,回过头去看一看我们之前的调用方式:

看一下源码,发现


实际上,payload这个参数就是传的null,那也就是说如果传一个不为null的参数,就可以对列表项中的具体控件更新了?

http://stackoverflow.com/questions/33176336/need-an-example-about-recyclerview-adapter-notifyitemchangedint-position-objec

我了解到这个方法的使用方式是这样的:


然来,onBindViewHolder有这么一个重载方式,如是我也这么做了,在下面这个重载中,去更新我想更新的控件:


然后,更新的方式变成了这种:


是骡子是马,那就在遛一遛吧!

然而,依然是会闪一下!!!这这么会!!!还是调试一下吧,新重载onBindViewHolder方法有没有被执行,一更代码,发现果然没有被执行! 那么,究竟是什么鬼?去网上查了一下,有人给出了一个解决办法:

http://stackoverflow.com/questions/32463136/recyclerview-adapter-notifyitemchanged-never-passes-payload-to-onbindviewholde


需要重写这个动画,让永远返回true,已达到newHolder和olderHolder是同一个,然而,这真的就是我的救命稻草吗?


那么,是骡子是马,拉出来溜溜吧,然而,并不是马!!进源码看一看


发现其实只要我们传入的payload不为空,那么返回的就是true?重写有意义吗?显然,我重载的onBindViewHolder方法并没有执行的原因显然不是这个。

那么,到底,到底问题出在何处?会不会是XrecyclerView的问题?根据调用栈,我看到第一个onBindViewHolder被执行了,往上面跟,发现XrecyclerView的实现果然存在问题!



如图,作者仅仅只实现了,不带payload的方法,最后adapter调用的只有不带paylaod的方法!所以,重写一个吧!


最后!终于达到了想要的效果了,经过这次爬坑,选择一个开源的框架真滴是需要慎重再慎重。

总结

实际上RecyclerView做局部刷新是非常容易的,其实就是使用好带payload参数的这个notifyItemRangeChanged方法,以及override带payload的这个onBindViewHolder方法,在onBindViewHolder中去刷新你想更新的控件即可,并非是网上传闻的那些原因,当然此处爬坑时间之长,也可能更选用开源控件不当有关,所以,选择开源控件,要谨慎再谨慎!





$(".MathJax").remove();


http://www.taodudu.cc/news/show-8154317.html

相关文章:

  • 【ESP32_Py_Board】LCD显示图片,文字,B站粉丝数
  • python某鱼主播粉丝的爬取
  • php中验证码刷新代码,php点击验证码实时刷新的实现代码
  • Unity3D塔防游戏开发——学习笔记(上)
  • 【python游戏】这年头塔除了拆还能干什么?这款好玩上瘾的塔防游戏,了解一下嘛
  • Unity3D Reset事件的触发
  • Unity3D-场景中3D物体添加点击事件
  • Echarts 3D地图+scatter3D 实现鼠标点击事件
  • unity 3D物体使用EventSystem响应事件
  • Unity3D的事件函数
  • Unity3d 3D物体上实现事件监听
  • Unity3D基于事件机制的消息系统
  • 【愚公系列】2023年10月 WPF+上位机+工业互联 035-图形3D与事件(3D对象)
  • Unity3d Ugui 24 EventSystem事件机制
  • 初学unity 3D-按钮点击事件触发函数
  • unity3d---物体加点击事件
  • Unity3D 委托和事件的区别
  • unity3d android 触摸事件,解决Unity3D关于手机触屏事件的方法
  • mars3d的各种事件
  • win8连接wifi成功但受限制_电脑连无线网提示无线网络受限制?路由电脑都重启了没用...
  • 无线网络一直连接限制
  • 计算机在受限的诊断状态下运行,笔记本win7旗舰版系统网络连接受限制或无连接的修复...
  • cisco路由器连接的两个网络_路由器无线网络受限制或无连接怎么办
  • 中国移动应用内计费平台服务器接口示例代码之“非官方”的一些说明
  • SEO优化规范(新浪2010.06)
  • 小学英语计算机融合课说课稿,小学英语和微机整合说课稿
  • 在SQL Server Management Studio中打开BAK文件恢复数据库
  • kali渗透之DC-4
  • AutoCAD 2006网络版授权文件配置
  • 读书笔记:沉默
  • 这篇关于RecycleView局部刷新闪动的问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



    http://www.chinasem.cn/article/346704

    相关文章

    IDEA和GIT关于文件中LF和CRLF问题及解决

    《IDEA和GIT关于文件中LF和CRLF问题及解决》文章总结:因IDEA默认使用CRLF换行符导致Shell脚本在Linux运行报错,需在编辑器和Git中统一为LF,通过调整Git的core.aut... 目录问题描述问题思考解决过程总结问题描述项目软件安装shell脚本上git仓库管理,但拉取后,上l

    idea npm install很慢问题及解决(nodejs)

    《ideanpminstall很慢问题及解决(nodejs)》npm安装速度慢可通过配置国内镜像源(如淘宝)、清理缓存及切换工具解决,建议设置全局镜像(npmconfigsetregistryht... 目录idea npm install很慢(nodejs)配置国内镜像源清理缓存总结idea npm in

    pycharm跑python项目易出错的问题总结

    《pycharm跑python项目易出错的问题总结》:本文主要介绍pycharm跑python项目易出错问题的相关资料,当你在PyCharm中运行Python程序时遇到报错,可以按照以下步骤进行排... 1. 一定不要在pycharm终端里面创建环境安装别人的项目子模块等,有可能出现的问题就是你不报错都安装

    idea突然报错Malformed \uxxxx encoding问题及解决

    《idea突然报错Malformeduxxxxencoding问题及解决》Maven项目在切换Git分支时报错,提示project元素为描述符根元素,解决方法:删除Maven仓库中的resolv... 目www.chinasem.cn录问题解决方式总结问题idea 上的 maven China编程项目突然报错,是

    Python爬虫HTTPS使用requests,httpx,aiohttp实战中的证书异步等问题

    《Python爬虫HTTPS使用requests,httpx,aiohttp实战中的证书异步等问题》在爬虫工程里,“HTTPS”是绕不开的话题,HTTPS为传输加密提供保护,同时也给爬虫带来证书校验、... 目录一、核心问题与优先级检查(先问三件事)二、基础示例:requests 与证书处理三、高并发选型:

    前端导出Excel文件出现乱码或文件损坏问题的解决办法

    《前端导出Excel文件出现乱码或文件损坏问题的解决办法》在现代网页应用程序中,前端有时需要与后端进行数据交互,包括下载文件,:本文主要介绍前端导出Excel文件出现乱码或文件损坏问题的解决办法,... 目录1. 检查后端返回的数据格式2. 前端正确处理二进制数据方案 1:直接下载(推荐)方案 2:手动构造

    Python绘制TSP、VRP问题求解结果图全过程

    《Python绘制TSP、VRP问题求解结果图全过程》本文介绍用Python绘制TSP和VRP问题的静态与动态结果图,静态图展示路径,动态图通过matplotlib.animation模块实现动画效果... 目录一、静态图二、动态图总结【代码】python绘制TSP、VRP问题求解结果图(包含静态图与动态图

    MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

    《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

    k8s容器放开锁内存限制问题

    《k8s容器放开锁内存限制问题》nccl-test容器运行mpirun时因NCCL_BUFFSIZE过大导致OOM,需通过修改docker服务配置文件,将LimitMEMLOCK设为infinity并... 目录问题问题确认放开容器max locked memory限制总结参考:https://Access

    Java中字符编码问题的解决方法详解

    《Java中字符编码问题的解决方法详解》在日常Java开发中,字符编码问题是一个非常常见却又特别容易踩坑的地方,这篇文章就带你一步一步看清楚字符编码的来龙去脉,并结合可运行的代码,看看如何在Java项... 目录前言背景:为什么会出现编码问题常见场景分析控制台输出乱码文件读写乱码数据库存取乱码解决方案统一使