安卓易学,爬坑不易—腾讯大佬的RecyclerView局部刷新爬坑之路

前言

安卓开发者都知道,RecyclerView比ListView要灵活的多,但不能否认的里面的坑也一样埋了很多人。下面让咱们看看腾讯开发工程师用实例讲解本身踩坑时的解决方案和心路历程。html

话说有图有真相,首先来对比一下局部刷新先后的效果:面试

优化以前的效果:api

优化以后的效果:框架

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

那么,这是如何作到的呢?这是本文的重点,本文的大纲主要包括:学习

  1. 分析为何会闪一下
  2. 对分析的可能形成闪动的问题进行解决
  3. 验证是否解决

 1、为何会闪一下?

咱们的需求是你们已经看到了,点击打分,弹出一个对话框,点击一个分数,这时候,经过一些列复杂的转换(固然不是本文的论述的重点),这时候到了要更新列表项了,如是很天然,咱们会这么作:优化

由于,操做的那个列表项你是知道他的position,因此你能够这么作,(固然,我以前是直接notifyDataSetChanged的,这个会照成因此不不要的item也会刷新)然而,闪动仍是出现了,那么我开始怀疑:动画

  1. 流传甚为普遍的一种说法,imageView的宽高不固定致使的(wrap_content)?
  2. 这个是RecyclerView自带的更新动画效果致使的?
  3. 这个是由于图片加载框架(glide 的 animte)的动画效果致使的?
  4. getView中(RecyclerView中是onBindViewHolder)加载图片的时候,设置一个tag,当发现这个imageView的tag和以前的tag一致时就不加载

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

一、对于第一种,个人作法是本身写了一个自定义的imageView,重写omMeasure方法,以下: spa

由于咱们的这个列表项中的图片是(高=宽)的,所以,我才这么写,这样写也有一个好处,不用在onBindViewHolder中去动态的计算出高度,而后在已layoutParm的方式设置给imageView,相信很多小伙伴都作过了吧! 3d

然而,遗憾的是,他并无解决闪一下的问题!此时这个闪动的缘由显然不在这里,可是这里作的,能够保留下来。

二、对于第二种说法,我参考了这里http://stackoverflow.com/ques...

的作法:

以及也尝试了这种

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

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

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

4、那么,就剩下最后一个猜想了,那么会不会是它呢?那就试试吧,因而代码改成:

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

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

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

能够看到这里有一个payload的参数,use null to identify a "full" update这是说若是传null就是所有更新,回过头去看一看咱们以前的调用方式:

看一下源码,发现

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

http://stackoverflow.com/ques...

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

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

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

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

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

http://stackoverflow.com/ques...

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

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

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

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

image

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

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

总结

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

原文连接:http://wetest.qq.com/lab/view...

阅读更多

kotlin学习笔记-异常好玩的list集合总结
一份完整的Android Studio搭建Flutter教程

NDK项目实战—高仿360手机助手之卸载监听

(Android)面试题级答案(精选版)

相信本身,没有作不到的,只有想不到的

在这里得到的不只仅是技术!

image

相关文章
相关标签/搜索