ViewStub你真的了解嗎


目錄介紹

  • 01.什么是ViewStub
  • 02.ViewStub構造方法
  • 03.inflate()方法解析
  • 04.WeakReference使用
  • 05.ViewStub為何無大小
  • 06.ViewStub為何不繪制
  • 07.可以多次inflate()嗎
  • 08.ViewStub不支持merge
  • 09.ViewStub使用場景
  • 10.ViewStub總結分析

好消息

  • 博客筆記大匯總【16年3月到至今】,包括Java基礎及深入知識點,Android技術博客,Python學習筆記等等,還包括平時開發中遇到的bug匯總,當然也在工作之余收集了大量的面試題,長期更新維護並且修正,持續完善……開源的文件是markdown格式的!同時也開源了生活博客,從12年起,積累共計N篇[近100萬字,陸續搬到網上],轉載請注明出處,謝謝!
  • 鏈接地址:https://github.com/yangchong211/YCBlogs
  • 如果覺得好,可以star一下,謝謝!當然也歡迎提出建議,萬事起於忽微,量變引起質變!

01.什么是ViewStub

  • ViewStub 是一個看不見的,沒有大小,不占布局位置的 View,可以用來懶加載布局。
  • 當 ViewStub 變得可見或 inflate() 的時候,布局就會被加載(替換 ViewStub)。因此,ViewStub 一直存在於視圖層次結構中直到調用了 setVisibility(int) 或 inflate()
  • 在 ViewStub 加載完成后就會被移除,它所占用的空間就會被新的布局替換。

02.ViewStub構造方法

  • 先來看看構造方法:
  • 接下來就看看關鍵的方法,然后看看初始化狀態setVisibility方法。

03.inflate()方法解析

  • 核心來了,平時用的時候,會經常調用到該方法。inflate() 是關鍵的加載實現,代碼如下所示:
  • Inflate使用特點
    • ViewStub只能被Inflate一次,inflate之后ViewStub對象就會被置為空。即某個被ViewStub指定的布局被Inflate后,就不能夠再通過ViewStub來控制它了。
    • ViewStub只能用來Inflate一個布局文件,而不是某個具體的View,當然也可以把View寫在某個布局文件中。

04.WeakReference使用

  • 使用了弱引用管理對象的創建,代碼如下所示
    • 在這里使用了get方法
    • 在這里創建了弱引用對象

05.ViewStub為何無大小

  • 首先先看一段源碼,如下所示:
  • 有沒有覺得很與眾不同
    • draw和dispatchDraw雖然重寫了,但是看代碼卻都是什么也不做!並且onMeasure還什么也不做,直接setMeasuredDimension(0,0);來把view區域設置位0,原來一個ViewStub雖然是一個view,卻是一個沒有任何顯示內容,也不顯示任何內容的特殊view,並且對layout在加載時候不可見的。

06.ViewStub為何不繪制

  • 具體看一下setWillNotDraw(true)方法,代碼如下:
  • View中,對於WILL_NOT_DRAW是這樣定義的:
  • 設置WILL_NOT_DRAW之后,onDraw()不會被調用,通過略過繪制的過程,優化了性能。在ViewGroup中,初始化時設置了WILL_NOT_DRAW,代碼如下:
  • 所以,在寫自定義布局時,如果需要調用onDraw()進行繪制,則需要在初始化時候,調用setWillNotDraw(false)。若是想要更進一步閱讀View中WILL_NOT_DRAW的相關源碼,可以去看下PFLAG_SKIP_DRAW相關的代碼。

07.可以多次inflate()嗎

  • ViewStub對象只可以Inflate一次,之后ViewStub對象會被置為空。同時需要注意的問題是,inflate一個ViewStub對象之后,就不能再inflate它了,否則會報錯:ViewStub must have a non-null ViewGroup viewParent。。
  • 其實看一下源碼就很好理解:
  • 其實也可以用一張圖來理解它,如下所示,摘自網絡
    • image
  • 也就是說,一旦調用inflate上面的方法后ViewStub就會變成null了,因此使用該對象特別需要注意空指針問題。

08.ViewStub不支持merge

  • 不能引入包含merge標簽的布局到ViewStub中。否則會報錯:android.view.InflateException: Binary XML file line #1: <merge /> can be used only with a valid ViewGroup root and attachToRoot=true

09.ViewStub使用場景

  • 一般的app中大多有這么一個功能,當加載的數據為空時顯示一個數據為空的視圖、在數據加載失敗時顯示加載失敗對應的UI,當沒有網絡的時候加載沒有網絡的UI,並支持點擊重試會比白屏的用戶體驗更好一些。俗稱,頁面狀態切換管理……一般來說,加載中、加載失敗、空數據等狀態的UI風格,在App內的所有頁面中需要保持一致,也就是需要做到全局統一,也支持局部定制。
  • ViewStub的優勢在於在上面的場景中,並不一定需要把所有的內容都展示出來,可以隱藏一些View視圖,待用戶需要展示的時候再加載到當前的Layout中,這個時候就可以用到ViewStub這個控件了,這樣可以減少資源的消耗,使最初的加載速度變快。
  • 那么就有了之前開發使用的狀態管理器開源庫,就是采用了ViewStub這個控件,讓View狀態的切換和Activity徹底分離開。用builder模式來自由的添加需要的狀態View,可以設置有數據,數據為空,加載數據錯誤,網絡錯誤,加載中等多種狀態,並且支持自定義狀態的布局。可以說完全不影響性能……

10.ViewStub總結分析

  • 分析源碼的原理,不管認識到哪一步,最終的目標還是在運用上,即把看源碼獲得的知識用到實際開發中,那么關於ViewStub的使用技巧,具體可以看我的狀態管理器案例,鏈接地址:https://github.com/yangchong211/YCStateLayout
  • 歡迎你的star,這也是開源和寫博客的源源動力,哈哈

ViewStub狀態管理庫:https://github.com/yangchong211/YCStateLayout

開源博客大匯總:https://github.com/yangchong211/YCBlogs


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM