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

寫在前面

在上一年的時候我曾經寫了一篇<<在RecyclerView中實現定點刷新>>的文章介紹瞭如何使用DataBinding框架進行局部刷新。時隔將近一年,期間我也換了一份工做,在新公司裏並無使用到DataBinding,因此若是想進行局部刷新ui,可能須要使用較早的adapter.notifyItemChanged(pos)git

近期在作一個功能的時候,發現有一個比較簡即可行的方法,能夠達到局部刷新的效果。github

那麼方法是什麼呢?

其實思考🤔一下,若是要更新一個TextView的文本,須要怎麼作呢?編程

答案很是簡單:那就是找到這個TextView,而後調用它的setText方法。markdown

代碼的話,多是這樣 :框架

findViewById<TexView>(R.id.titleTv).text = "title"
複製代碼

上面的是指普通的View,那麼在RecyclerView呢?oop

其實答案差很少,咱們只須要找到對應的ItemView或者它的ViewHolder,而後調用對應的渲染ui的方法就好了。先看看效果:post

那應該怎麼作呢?優化

一個簡單的方法

其實RecyclerView已經提供了根據position獲取ViewHolder這個功能。ui

從方法裏能夠看到RecyclerView會for循環去找holder,而後比較位置,若是不爲null,且沒有被移除,那麼表明能夠找到了,反之則爲null。this

那怎麼找呢?

其中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.cn/user/817692…

Github: github.com/ditclear

相關文章
相關標籤/搜索