可視化 ListView 緩存機制,手摸手帶你打通任督二脈

項目地址:ListViewVisualizationgit

簡介

本文不涉及 ListView 緩存機制的源碼探析,關於 ListView 的緩存機制郭霖前輩的《Android ListView工做原理徹底解析,帶你從源碼的角度完全理解》已經分析的很通徹了,同理網上也有不少文章了。本文不針對 ListView 的緩存機制作介紹,對於這塊還不夠了解的朋友能夠閱讀上方郭霖前輩的文章。另外再配上騰訊 Bugly 的圖:github

這裏寫圖片描述

痛點

對於像 ListView/RecyclerView 這種級別 View 的源碼是長篇且晦澀的,連郭霖前輩本身也說過 「沒過幾個月時間我就把當初梳理清晰的源碼又忘的一乾二淨」。且網上的文章都是針對代碼闡述的,實在是有些難以理解,且部分知識點並未涉及(例如僅針對 ViewType 只有一種狀況的情形作說明,多 ViewType 情形下緩存機制少見闡述)。筆者遇到這些問題時候仍是很頭疼的,因而就將 ListView 的緩存機制給可視化,再針對各個情形加以總結,相信能幫助到不少對 ListView 緩存機制不太熟悉的讀者們。數組

緩存機制解析

項目地址:ListViewVisualization或者你能夠直接安裝:apk。 在手摸手解析以前,須要說起到 RecycleBin 中的幾個字段 ,這些字段在郭霖前輩的文章中基本都有所說起,實際上掌握了這些字段在 ListView 緩存機制中變換的狀況,筆者認爲對 ListView 的緩存機制瞭解就算是比較通徹的了——緩存

  • mCurrentScrap:ArrayList 類型,用於存儲離屏的 View
  • mScrapViews
    • ArrayList [] 類型
    • 數組中每一個元素都是 ArrayList 類型,效果同 mCurrentScrap
    • mScrapViews[0] 就是 mCurrentScrap
    • 其數組長度應爲 ViewTypeCount。由於針對不一樣的 ViewType,ListView 都要有一個專門的 ArrayList 鏈表來緩存它對應的 View
  • mActiveView:ArrayList 類型,被 layoutChildren() 用於緩存屏幕上的 View。

文章中說起的部分名詞:項目中 ListView 使用了兩個 ViewType,也就是有兩種佈局,其中第一種筆者在文中說起到時命名爲 Item1,第二種稱爲 Item2app

初始化

這裏寫圖片描述

mActiveViews:長度爲4。在筆者的手機上初始化時屏幕上只能容下4個 View mScrapViews:長度爲2。筆者設置了兩種 ViewType,因此須要有兩套緩存 View 的 ArrayList mCurrentScrap/mScrapViews[0]:長度爲0。此時緩存區確定是0,由於沒有滑動因此不存在緩存 View 一說。 mScrapViews[1]:長度爲0。這個就更不解釋啦。 佈局

觸發第一個緩存

這裏寫圖片描述

當 『1』 被移出屏幕的時候,mCurrentScrap/mScrapViews[0] 就要動手將它緩存起來啦,做爲下一個進入屏幕的 View 的複用。在圖上此時也多出了一句 the last one of mCurrentScrap's type is ItemX---number,爲何要關注 mCurrentScrap 的最後一個值?由於 RecycleBin 在滑動區域都是 Item1 的狀況下,取出緩存的方式就是從末尾獲取一個 View,因此咱們須要關注一下末尾 View 的類型,可是實際上在整個過程當中該值的意義也並不大,純粹是爲了展現離屏 Item 信息。至於 ItemX 後面的數字,則是廢棄 View 中 TextView 中所顯示的 text 了。因此第一個緩存是一個 Item1 類型的 TextView 顯示爲 1 的 View 被移出屏幕了。.net

同理:當『2』被滑出屏幕的時候,『2』這個 View 將會被緩存起來,此時屏幕上應該顯示了 the last one of mCurrentScrap's type is Item1---2,各位讀者能夠試試。debug

屏幕內容數量最大化

屏幕繼續下滑啊下滑~

這裏寫圖片描述

屏幕下滑沒多少就會忽然發現 mCurrentScrap/mScrapView[0] 爲 0 啦,這說明此時 RecycleBin 中沒有緩存!由於此時屏幕中已經顯示了 『2』~『6』共 5 個 View 了,以前的 『1』 已經被 『6』 複用了,因此不存在還有緩存了。實際上針對於 ViewType 只有一種的狀況來講,RecycleBin 機制中的 mCurrentScrap/mScrapViews[0] 的大小永遠是1。由於它至多隻須要緩存一個 View,由於屏幕內容數量的最大值一定爲初始時屏幕內容數量值 + 1,拿筆者的手機舉例來講,初始值爲4,屏幕內容數量的最大值則爲 5。code

觸發 Item2 的顯示

筆者將 Item1 的數量設置爲 17,當咱們挪到 17 繼續下滑時將會發生什麼情形?

這裏寫圖片描述

一切都在掌控以內。cdn

繼續觸發

屏幕繼續下滑,直至『14』被移出屏幕——

這裏寫圖片描述

當『14』被移出後,mCurrentScrap/mScrapViews[0] 的 size 從百年不變的 1 變成了 2。爲何?由於『13』 用不上了,新出來的 View 是 Item2 而不是 Item1,因此緩存只能無奈的加加加,而不能被複用。咱們不妨移動到全屏爲 Item2 ——

這裏寫圖片描述

直至『17』移出屏幕,mCurrentScrap/mScrapViews[0] 的大小最終達到了 5。

總結

什麼玩意兒,剛進 Item2 區域就總結啦?就總結啦!由於純粹的 Item2 區域滑動和純粹的 Item1 區域滑動狀況是同樣的;而 Item2 區域滑向 Item1 區域的情形與 Item1 區域滑向 Item2 區域的情形也是同樣的。因此本文授人以漁的任務就完成了,剩下的就是各位讀者實操捕魚的過程了。
相關文章
相關標籤/搜索