天天看點

android viewbinding_終于有人寫:新技術ViewBinding 的本質了

本文作者

作者:codelang

連結:

https://juejin.im/post/5e8090ae6fb9a03c3d7372a2

本文由作者授權釋出。

之前提到:

總覺得 ViewBinding 和 DataBinding 能力非常類似,于是又找了一些和 DataBinding 的差別文章來看,恩...還是沒有看到太本質的差別,後面可能會詳細的對比一波,有比較了解的也歡迎留言,先看看這篇 ViewBinding 實戰吧。

碼農西哥,公衆号:鴻洋ViewBinding 實戰,遞進優雅的寫波代碼

今天終于看到一篇帶大家從本質來了解 ViewBinding 了。

如果你完全沒了解過 View Binding,可以先看下面這篇介紹:

AS 3.6 Canary 中推出新技術 視圖綁定 View Binding

今天我們來深入的了解 ViewBinding 的本質,看看他是怎麼生成 ActivityMainBinding 這種檔案的。

1 使用

ViewBinding 目前隻支援 as3.6,使用方法很簡單,僅僅隻需要添加如下代碼:

make project 之後,會在對應的 module 路徑:

app/build/generated/data_binding_base_class_source_out/${buildTypes}/out/${包名}/databinding

生成 ViewBinding 檔案,為什麼我會說 對應的 module ?因為 viewBinding 隻對目前設定了 enabled = true 的 module 才會進行處理。

然後來看下處理後的檔案:

我們來看看這個檔案有哪些資訊:

  • R.layout.activity_main 布局檔案
  • 布局檔案中的 view 控件和 view id
  • 布局檔案的 rootView 和類型

接下來,我們會通過源碼的方式來跟蹤到,這些資訊是怎麼産生的。

具體使用可以參考文章:

[譯]深入研究ViewBinding 在 include, merge, adapter, fragment, activity 中使用

https://juejin.im/post/5e4806f3e51d4526c550a2ef

2  準備

由于我們并沒有依賴其他 plugin 就可以使用,是以能被直接識别隻能是 classpath 依賴的 gradle 了:

classpath 'com.android.tools.build:gradle:3.6.1'

既然 make project 之後就可以看到 ViewBinding 的生成類,那麼,我們可以根據 make project 的 build 資訊檢視做了哪些 task:

沒有找到 ViewBinding,但找到了 dataBinding,但可以肯定的是,這個 dataBinding 就是生成 ViewBinding 的 task(因為沒有其他的 task 帶有 binding)。

然後我們可以去 maven 倉庫找一下 gradle:3.6.1 ,驚喜的是,gradle:3.6.1 的依賴項有 18 個,第一個就是 Data Binding Compiler Common:

https://mvnrepository.com/artifact/com.android.tools.build/gradle/3.6.1

android viewbinding_終于有人寫:新技術ViewBinding 的本質了

然後我們進去找到對應的 compiler 3.6.1 版本,通過 gradle 依賴,我們就能看到源碼了:

https://mvnrepository.com/artifact/androidx.databinding/databinding-compiler-common/3.6.1

compile group: 'androidx.databinding', name: 'databinding-compiler-common', version: '3.6.1'
android viewbinding_終于有人寫:新技術ViewBinding 的本質了

可以看到,ViewBinding 是屬于 dataBinding 庫裡面的一個小功能。

3  階段一:收集元素

由于我們僅僅隻是檢視 dataBinding compiler,是以,對于 gradle 調用 compiler 的哪個部分進行聯結,我們是檢視不到的,但這也不影響我們跟蹤源碼。

我們直接來看 :

LayoutXmlProcessor.java

我們直接來看 全量編譯檔案處理 :

①、判斷目前的檔案夾的檔案名 startWith 是否是 layout 

②、會建立一個檔案輸出目錄, 輸出目錄為 new File(input.getRootOutputFolder(),file path); 這個 file path 做了與輸入目錄的 relativize 化,其實,可以了解為,這個輸出目錄為 輸出目錄 + file 檔案名 。

③、判斷 layout 下面的檔案名 endWith 是否是 .xml 

④、處理 xml 檔案,這個地方也會建立一個輸出目錄,跟 ② 的方式一樣,最終,這個方法會

調用到 processSingleFile 方法

然後我們來看下 processSingleFile 方法:

①、這個地方會拿着 xml 檔案的路徑和輸出路徑進行解析

②、将解析結果緩存起來

然後來看下 xml 的解析 parseXml

LayoutFileParser.java

parseOriginalXml:

①、是否是 databinding,這個的判斷依據是,根元素是否是 layout , 擷取 data 和 rootView

②、isViewBindingEnable 就是 gradle 設定的 enable = true,根元素就是就是他的 rootView,這個地方要注意的是 data = null,data 資料隻有 databinding 才會有的元素,viewBinding 是不會去解析的

③、解析表達式,這裡面會循環周遊元素,解析 view 的 id、tag、include、fragment 等等 xml 相關的元素,并且還有 databinding 相關的 @={ 的表達式,最後将結果緩存起來,源碼我就補貼了,太多,影響文章

4  階段二:寫 Layout 檔案

LayoutXmlProcessor.java

①、周遊之前收集到的所有 LayoutFileBundle,寫入 xmlOutDir 路徑

②、生成 LayoutFileBundle 的檔案名,這個檔案名最終生成為:

layout.getFileName() + '-' + layout.getDirectory() + ".xml

例如 activity_main.xml,生成的 fileName 為 activity_main-layout.xml

③、将 LayoutFileBundle 轉換 xml ,寫入檔案

由于我們是直接跟蹤的 databinding compiler 庫,是以無法跟蹤到 gradle 是什麼聯結 compiler 庫的,是以,xmlOutDir 我是未知的,也不知道他存到了哪,但沒有關系,我們既然知道了生成的檔案名規則,我們可以全局搜尋該檔案,最終,我們在該目錄中搜尋到:

app/build/intermediates/data_binding_layout_info_type_merge/debug/out/activity_main-layout.xml

檔案内容如下:

這份 xml 描述了原始 layout 的相關資訊,對于 include 和 merge 是怎麼關聯 tag 的,讀者可以自行運作檢視

5  階段三:寫 ViewBinding 類

BaseDataBinder.java

可以看到,最後又去讀之前生成的 layout xml,這個地方為什麼會又寫又讀,而不是直接利用之前 layout 的緩存?我想可能是因為解耦,他們都是獨立的 task。

然後來看是如何生成 Binding 類的:

①、toViewBinder 是 BaseLayoutModel 的拓展函數,他會将 LayoutFileBundle 包裝成 ViewBinder 類傳回 

②、toJavaFile 是 ViewBinder 的拓展函數,該拓展函數在 ViewBinderGenerateSource 類中

ViewBinderGenerateSource.java

這個地方就貼 typeSpec 方法了,具體的,大家可以自己去看源碼,從 typeSpec 中,我們就可以看到點生成的 ViewBinding 類包含了哪些東西,rootView 字段,inflater 、bind 方法。

總結

文章已經盡量保持源碼簡短,隻貼核心部分。本來還想絮絮叨叨一下,算了,就到這。

最後推薦一下我做的網站,玩Android: wanandroid.com ,包含詳盡的知識體系、好用的工具,還有本公衆号文章合集,歡迎體驗和收藏!

推薦閱讀:

代碼潔癖症的我,學習Lint學到心态爆炸 一段代碼引發的問題,== , equals包含多少知識 關于Handler 的這 15 個問題,你都清楚嗎?

android viewbinding_終于有人寫:新技術ViewBinding 的本質了

掃一掃 關注我的公衆号

如果你想要跟大家分享你的文章,歡迎投稿~

┏(^0^)┛明天見!