你可能不知道的在RecyclerView中实现局部刷新的技巧

写在前面

在上一年的时候我曾经写了一篇<<在RecyclerView中实现定点刷新>>的文章介绍了如何使用DataBinding框架进行局部刷新。时隔将近一年,期间我也换了一份工做,在新公司里并无使用到DataBinding,因此若是想进行局部刷新ui,可能须要使用较早的adapter.notifyItemChanged(pos)git

近期在作一个功能的时候,发现有一个比较简即可行的方法,能够达到局部刷新的效果。github

那么方法是什么呢?

其实思考🤔一下,若是要更新一个TextView的文本,须要怎么作呢?编程

答案很是简单:那就是找到这个TextView,而后调用它的setText方法。框架

代码的话,多是这样 :post

findViewById<TexView>(R.id.titleTv).text = "title"
复制代码

上面的是指普通的View,那么在RecyclerView呢?优化

其实答案差很少,咱们只须要找到对应的ItemView或者它的ViewHolder,而后调用对应的渲染ui的方法就好了。先看看效果:ui

那应该怎么作呢?this

一个简单的方法

其实RecyclerView已经提供了根据position获取ViewHolder这个功能。spa

从方法里能够看到RecyclerView会for循环去找holder,而后比较位置,若是不为null,且没有被移除,那么表明能够找到了,反之则为null。线程

那怎么找呢?

其中childCount是经过 this.mChildHelper.getUnfilteredChildCount()获得的。

其最终会调用RecyclerView的getChildCount()方法,返回的结果表示可见的item个数。好比当前可见的是8个,那么childCount便是8,因此你想获取超过屏幕最大Index的ViewHoler,那么就会返回null。好比当前最大可见的position为13,若是你想找第11个,可以获取到,可是找第15个,那么会返回null。

接着咱们来拆解获取ViewHolder的方法,以下所示:

getChildViewHolderInt(this.mChildHelper.getUnfilteredChildAt(i));
复制代码

首先会经过getUnfilteredChildAt获取到index对应的view。这个方法最后也是调用的RecyclerView的getChildAt(offset)方法。

找到View以后,再用getChildViewHolderInt(view)获取对应的ViewHolder,其内部实现以下:

即经过LayoutParams获取到相应的ViewHolder。

而将ViewHolder赋值给LayoutParams的过程出如今RecyclerView的getViewForPosition(pos)方法中,最终会被LayoutManager调用。

回到主题,如今咱们获取到了想要的ViewHoler,并且也知道了当前的Position,那么只须要再调用Adapter的

onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int)便可。

固然由于在Adapter中也能获取到RecyclerView,因此能够将更新的方法放入到Adapter中。

数据变化的时候,调用notifyItemUpdate(pos:Int)便可,能够说是很简单了。

写在后面

若是要说再优化的话,固然也有继续优化的点,好比减小无用的更新,或者说能在子线程通知更新UI,固然这些都是后话,之后再来完善。

GitHub示例:github.com/ditclear/Bi…

==================== 分割线 ======================

若是你想了解更多关于MVVM、Flutter、响应式编程方面的知识,欢迎关注我。

你能够在如下地方找到我:

简书:www.jianshu.com/u/117f1cf0c…

掘金:juejin.im/user/582d60…

Github: github.com/ditclear

相关文章
相关标签/搜索