咱們項目採用的是 kotlin && DataBinding 處理的,可能你會疑問,既然用的是 kotlin,爲啥沒有用 kotlinx?新的頁面固然是用的 kotlinx 啦,但咱們有至關龐大的歷史代碼,而且咱們的通用 adapter 其實也是基於 DataBinding 來封裝的。因此,咱們仍是不得不來討(吐)論(槽)一下這個 DataBinding 的坑。事實上,這個問題在我當年面試字節跳動的時候就被問及過。android
這是一個很是開放性的問題,因此看到這篇文章的小夥伴必定得帶一個有色眼鏡進行審視,下面會盡量地列舉中筆者遇到過的坑,固然能力有限,有可能很多東西並非 DataBinding 的問題,須要你們一塊兒來甄別並進行補充。git
DataBinding 是早些時候 Google 推出來的一個支持庫,只要敢於解決咱們代碼中頻繁出現的 findViewById()
問題,在此以前,我相信大部分人都聽過或者使用過 Butterknife,截止目前,該庫都已經更新到 10.1.0 了,並且做者是 JakeWharton 大神,實爲至關好用。github
但咱們今天不對 Butterknife 進行過多的評論,而轉移到咱們的主角 DataBinding。面試
對於 DataBinding 的使用和介紹這裏就不作講述了,建議你們仍是直接到 官方文檔
進行查閱學習,今天在這兒,主要和你們分享討論一下在筆者 1 年多的 DataBinding 中踩過的一些坑。我想這些 tips 確定不是所有,而且有些實際上是我的誤操所致,無論怎麼說,咱們今天就捨棄對它的讚美,吐槽吐槽這個 DataBinding。緩存
oh,這應該是使用 DataBinding 的小夥伴們最最最大的坑點了,你甚至必定在各類技術輪胎和開發交流羣中見過一些小夥伴對它的深惡痛絕。無論你代碼中有了什麼錯誤,你必定收到的錯誤日誌是一大堆 DataBinding 生成的類找不到。服務器
可能很是多的小夥伴會對此保持疑問,這不,真正的錯誤都在 build 日誌的最後能看到麼?實在沒有看到,你也能夠在控制檯輸入 ./gradlew build --stacktrace
查看到詳細日誌。組件化
但事實真的如此麼?有沒有小夥伴經歷過無論你怎麼查看日誌都找不到真正的錯誤代碼的。性能
我想必定有!雖然咱們通常都要求對 commit 保持「少許屢次」的原則,但這並不能保證咱們時刻都得嚴格遵照,在部分業務很是紊亂的時候,咱們並不但願常常作 commit,由於每一次 commit,咱們也得作一次編譯確認當前的代碼沒有任何語法問題。而對於代碼量龐大、尤爲是還受各類歷史緣由組件化不夠完全的項目,一次編譯基本就可讓你去吃一個飯了。我司的項目就是如此,受限於歷史緣由,組件化作的並不完全,致使本地編譯在沒有命中緩存的狀況下至少得 10 分鐘,這仍是在 16G 的 mac pro 上。並且大多數人的電腦可能配置還更低,在編譯的時候很難作其餘和工做相關的事情。學習
爲了處理這個編譯問題,我司不得不編寫一個編譯腳本,把編譯操做都在服務器上進行處理,在作了一系列優化操做後,在沒命中緩存的狀況下編譯 debug 包仍是須要 4.5 分鐘,固然如今在編譯中咱們能夠作其餘有意思的事情了。gradle
好像前面這兩段說了不少可有可無的東西,可是!我真正想要表達的是,這時候出現了錯誤,而且日誌沒法對錯誤進行定位,你會發現很是痛苦,你可能已經改動了數十個文件,新建了很多 XML,由於沒法定位到日誌,你不得不一行一行的進行語法檢查。
我在這個問題上體驗過編碼兩小時,查編譯失敗問題花費時間更多的尷尬狀況,一般來講,這樣的錯誤都不容易發現,我深深的記住我有一次由於組件化歷史問題,不得不把一個組件代碼 move 到另一個組件,而後就發生了不可預料的錯誤的悲痛場景。當你 stash
改動後就能夠編譯,但 pop
出來就錯誤的時候,你纔會知道什麼是手段極其殘忍。
OK,目前對於這樣的狀況,仍是有所總結,這種狀況 95% 是 XML 代碼的問題,你能夠直接檢查 XML 了。
咱們使用 DataBinding 的時候,必然會喜歡它的雙向綁定操做。在 XML 裏面直接作一些簡單的邏輯處理,這樣的操做讓咱們的代碼變得很是簡潔,而且能夠省去 findViewById()
帶來的沒必要要的性能損耗。但這樣的操做讓後續維護功能代碼的人很是痛苦。
咱們的代碼裏面就有至關部分的這樣的代碼,部分頁面邏輯很是複雜,好比一個商品詳情頁,會牽扯到很是大量的信息展現和各類促銷秒殺狀態,還有很多的動效,這時候很多邏輯放在 XML 裏面後,後續維護的同事在處理產品改動的時候,必定在心中暗自謾罵。
一般來講,我習慣於把這些複雜的邏輯放置在咱們的 Java 代碼中。就目前來看,在代碼中查看這些複雜的交互邏輯駕輕就熟很多。
早些時候,我連續犯過兩次低級錯誤,因此對這個問題記憶深入。咱們能夠發現,XML 裏面支持咱們用相似 @{}
這樣的方式去爲 TextView
設置顯示內容,但在 XML 裏面咱們並無檢測機制,因此極易出現本來你這個是一個 Number
類型的值,編譯器卻當作一個 resourceId
進行處理而報錯。實際上,在代碼裏面設置編譯器是會直接報錯的。
在咱們項目的早期代碼中,XML 裏面的命名規範基本是 xxx_xxx_xxx 這樣的格式,但在 DataBinding 裏面爲咱們生成的變量卻採用的是駝峯命名法,這致使咱們根據一個控件 id 去對應 class 裏面尋找的時候,還得本身更改成駝峯命名法命名的名字,這一度讓咱們感到很是不適,因此咱們後面的代碼 XML 命名規範就跟着變成駝峯命名法了。這可能和命名規範有些許出入,不過咱們堅信適合本身的,纔是最好的理念。
前面說到,咱們平時會採用服務器編譯,因此此前有出現過 XML 文件裏面的某個屬性設置在本地編譯不過,但在服務器上甚至其餘同事的電腦上能夠編譯的問題。老實說,目前我並無找到真正的緣由,我姑且把這個問題甩鍋給了此前作這個的同事。我後續更改了他的實現方式才讓這個問題獲得妥善處理,但至今沒有明白問題出在哪裏,由於那樣的方式我認爲自己代碼是沒有什麼問題的。惋惜我如今沒有時間去尋找這個代碼,大概是設置一個公用的 onClickListener
的問題。
咱們一般會用到 @BindingAdapter 方式來作一些公用邏輯,而不是直接去把邏輯放在頁面經過設置屬性來使用它,這樣就會出現這些公用邏輯比較難維護,固然,這極有多是咱們項目的歷史問題,但我以爲這算是一個坑點了。不知道有沒有人出現這樣的屬性在 XML 裏面沒有提示的狀況。就像你自定義 View Styleable 名字不惟一同樣。
這個問題我以前尚未發現,由於咱們每一個模塊都用到了 DataBinding,因此認爲每一個模塊的 gradle
都設置上 DataBinding 的配置,並不算什麼使人能夠吐槽的事,但看起來這個問題挺嚴重的,因此也在這分享給你們。轉自 wanAndroid 上面 xujiafeng 的回答}
DataBinding在多模塊開發的時候,有這樣一個機制:
若是子模塊使用了 DataBinding,那麼主模塊也必須在 gradle 加上配置,否則就會報錯;
若是主模塊和子模塊都添加上了 DataBinding 的配置,那麼在編譯時,子模塊的 XML 文件產生的 Binding 類除了在本身的 build 裏會有一份外,在主模塊下也會有一份。
那麼,若是主模塊與子模塊都有一個 layout 根目錄的 activity_main.xml,主模塊生成的 ActivityMainBinding 會是根據子模塊的文件生成的!這種狀況咱們還能夠經過讓主模塊和子模塊使用不一樣的命名,那麼下面這個問題就更要命了:若是子模塊的某個 XML 文件使用了一些第三方的控件,那麼主模塊因爲也會生成這個文件的 Binding 類,而且其會有第三方控件的引用,這時候因爲主模塊沒有引入這些控件,就會報錯,解決辦法是在子模塊應用第三方控件的時候,使用 API 的方式應用,這樣主模塊就堅定引用到了這些第三方控件,這是這樣違背瞭解耦的原則。
哎,我的能力有限,就想到哪兒說到哪兒了。可能有很多其實並非 databinding 的坑,是我的使用問題,還往明白的人能直接指出。PS:再給我一個機會,我不想在用 Databinding。
但願有其餘槽點或者認爲上面的東西是有更好的處理方式的小夥伴必定要在下面留言,盼復盼復~