RecyclerView高級進階之優雅地解決瀑布流的兩個神坑

1.前言

在RecyclerView上使用StaggeredGridLayoutManager佈局管理器很容易實現瀑布流佈局。瀑布流佈局比線性佈局和網格佈局美觀,手機屏幕空間利用率高,可是實現方式也比它們複雜,並且常常會有一些莫名奇怪的bug會在瀑布流佈局上出現,線性和網格則不會。java

原本將重點介紹瀑布流兩個臭名昭著的bug。經過深刻探索瀑布流佈局的實現原理,分析它們的造成緣由,並給出優雅解決它們的解決方案。git

1.1 bug1:頂部空白、重排序

bug復現操做:github

  1. 將瀑布流滑動到底部;
  2. 點擊刷新按鈕,調用Adapter.notifyDataSetChanged();
  3. 從下往上滑動瀑布流列表至頂部時手指離開屏幕。

bug描述數組

當滑動到頂部時,頂部出現空白,鬆手時瀑布流發生重排序,而且觸發了動畫。緩存

在實際的項目中,咱們不太但願用戶看到這種明顯的動畫,甚至不想用戶看到瀑布流頂部出現空白。markdown

1.2 bug2:瀑布流左右間距錯亂

bug復現操做同bug1框架

bug描述oop

「1漢皇重色...」和「5雲鬢花顏...」左側沒有對齊。整個瀑布流佈局有不少這樣的間距錯亂問題。佈局

2. 解決方案

2.1 bug1解決方案

網上的解決方案以下: 性能

該方法可以解決問題,可是比較耗性能。由於,它無論會不會出現空白狀況,都會清空mLazySpanLookup,而且從新佈局。

個人解決方案是,經過反射StaggeredGridLayoutManager的checkForGaps()。在滑動時,僅在有須要的狀況下才會從新佈局。

效果以下:一樣的操做,當滑到頂部時,空白問題解決了。可是bug2的問題仍然存在

2.2 bug2解決方案

本案例中,瀑布流每一個Item之間的間隔是10dp。屏幕兩側與Item之間的間隔也是10dp。我是經過ItemDecoration來實現的。

解決方案以下:

完美解決間距錯亂問題。

3. bug2產生緣由分析

瀑布流Span數組

在本案例中,瀑布流共四列。屏幕被分割成四個Span。每一個Span對應的下標分別是0、一、二、3。而左右間距正是根據下標變化的。若是下標不正確,那麼ItemView的間距也會計算錯誤。好比說「1漢皇重色...」的span原本應該是0,若是變成了1,那麼它的左邊距和右邊距就是5dp。而正確的應該是左間距10dp,右間距5dp。

觀察spanIndex錯亂

我分別在getItemOffsets()和animateMove()方法中打印spanIndex

zijiexiaozhan getItemOffsets 1漢皇重色思傾國,御宇多年求不得 index 1

zijiexiaozhan animate 1漢皇重色思傾國,御宇多年求不得 index 0

咱們知道「1漢皇重色思傾國」的正確的spanIndex是0。而在getItemOffsets中倒是1,在作動畫的時候又變成了正確的0。緣由可能有兩種

  1. getItemOffsets在設置spanIndex以前調用,致使getItemOffsets拿不到正確的spanIndex
  2. getItemOffsets在設置spanIndex以後調用,可是屢次設置spanIndex,因爲某種緣由getItemOffsets並無同步調用

分析fill方法

由圖咱們能夠看到設置spanIndex會在getItemOffsets方法前面調用,因此排除第一種可能性

分析getItemOffsets調用時機

在getItemOffsets中打斷點,得到調用棧以下

//RecyclerView.java 緣由是lp.mInsetsDirty在dispatchLayoutStep1階段被設置成true了。致使在dispatchLayoutStep2真正佈局階段,不會調用到getItemOffsets方法。從而致使缺失了一次更正Decoration繪製的機會。關於RecyclerView動畫原理,請查閱RecyclerView佈局和動畫原理一文

解決方案

解決方法就顯而易見了,在checkForGaps返回true後把lp.mInsetsDirty設成false。反射調用RecyclerView的markItemDecorInsetsDirty()

4.總結

RecyclerView是Android UI框架中一個很是重要的組件。它使用簡單,上手快。可是它的高級使用,一旦遇到問題,那就會變成一件很是棘手的事情。由於我專門寫了一系列關於RecyclerView高級進階的文章。包含了佈局原理、動畫原理、滑動原理、緩存實現機制、實戰踩坑填坑等方面。相信你學習完必定會有收貨。

本文案例已上傳到github。關注我回復「瀑布流」,獲取完整教程。

搜索框傳播樣式-標準色版.png

相關文章
相關標籤/搜索