[譯]Finding Views by ID的演進

作者:Wajahat Karim

時間:2020/4/1

原文: Evolution of Finding Views by ID in Android

findViewById() vs Butterknife vs Kotlin Synthetics vs DataBinding vs ViewBindings

長久以來,Android開發人員一直在努力解決一個簡單但煩人的問題。將XML佈局中View的引用以完全獨立的語言(Java或Kotlin)從其佈局視圖類(例如Activity或Fragments)中獲取。

作爲Android的初學者時,我曾感到很困惑。Android SDK提供了一個方法:findViewById()。功能方面,這個方法執行一個單一的任務——在XML佈局中查找ID,返回一個View的引用。如果什麼都沒找到,它將返回NULL,據說它的創造者稱其爲十億美元的錯誤。

在這篇文章中,我將探討findViewById()如何演進和在“現代Android開發”中如何從XML佈局中獲取一個View的引用。

——————————————————————————————————

findViewById()方法

顯然,首先是findViewById()方法。在API 1中引入,該方法需要一個ID作爲參數,返回一個View對象。
在這裏插入圖片描述

這種方法存在一些問題。

  • 如果在佈局中存在該ID的View,則不會出現任何編譯錯誤。相對地,當Android無法在Activity,Fragment,ViewGroup中找到該View時,將在運行時拋出NullPointerException。
  • 如果該View在XML佈局中是TextView,並且將其類型轉換爲Button,在編譯期同樣不會出錯。但運行時會拋出ClassCastException,因爲TextView無法轉換爲Button。

此方法被廣泛使用,並且貫穿了Android SDK的整個發展過程。在compileSdk API爲26時,略微修改了改方法以消除強制轉換問題。
在這裏插入圖片描述

現在,開發人員無需在代碼中手動強轉View。如果您引用使用Button來引用TextView的ID,則Android SDK會嘗試查找指定ID的Button,並且它將返回NULL,因爲無法找到它。

但是在Kotlin中,您仍然需要提供一個View類型像這樣:findViewById(R.id.txtUsername) 。這將拋出NullPointerException 如果你沒有做空安全檢查,但是這個方法不會像之前一樣拋出ClassCastException。

分析

  • 類型安全(Type-safe): 在API 26以前,非類型安全
  • 空安全(Null-safe): 無。在使用之前必須進行空檢查
  • 樣板代碼(Boilerplate Code): 很多。你必須爲每個在XML佈局中使用到的View定義一個單獨的變量
  • 構建時間(Build Time): 無差異
  • 語言(Languages): 支持Java和Kotlin

——————————————————————————————————

ButterKnife

很多庫都試圖通過不同的方法簡化findViewById()的使用。特別地,Jake Wharton開源的Butterknife尤爲出名並且引起了全球開發者的興趣。它已經成了避開使用findViewById()的標準方式。

該庫使用註解處理,並通過編譯期生成的代碼使用findViewById()方法從XML佈局中獲取View。它非常易於使用,並能有效減少開發人員的樣板代碼。
在這裏插入圖片描述

Butterknife具有與findViewById幾乎相似的問題。然而,它在運行時添加空安全檢查來避免NullPointerException。

注意: 現在不推薦使用此工具。請切換到view binding。當然,現有版本將繼續維護,但是僅考慮與AGP集成相關的關鍵錯誤的修復。功能開發和常規錯誤的修復已停止。 ——原文:Butterknife Github repository

分析

  • 類型安全(Type-safe): 非類型安全,因爲使用了findViewById
  • 空安全(Null-safe): 該庫運行時在view訪問前做了空判斷
  • 樣板代碼(Boilerplate Code): 通過註解處理器生成代碼來減少樣板代碼
  • 構建時間(Build Time): 構建時間受註解處理影響
  • 語言(Languages): 支持Java和Kotlin

——————————————————————————————————

Kotlin Synthetics

Android SDK現在是Kotlin優先(Kotlin-first)。這意味着Android SDK將首先從Kotlin的角度實現API,然後再爲Java添加這些API。

Kotlin引入的最大功能之一是Kotlin擴展方法(Kotlin Extension Methods)。在它的幫助下,Kotlin Synthetics誕生了。Kotlin Synthetics通過自動生成的Kotlin擴展方法,使開發人員可以從XML佈局直接訪問其視圖。
在這裏插入圖片描述

Kotlin Synthetics調用一次findViewById方法,然後默認情況下將view實例緩存在HashMap中。可以通過Gradle設置將此緩存配置更改爲SparseArray或不緩存。

總體而言,Kotlin Synthetics是一種很好的選擇,因爲它是類型安全的,並且需要通過Kotlin的“?”操作符進行空檢查如果view僅在一些佈局配置中存在。它不需要開發人員編寫額外的代碼。但這僅適用於Kotlin項目。

但是,許多開發人員在使用Kotlin Synthetics時遇到了一個小問題。例如,如果您將佈局設置爲content view,但輸入僅在其他佈局中存在的ID,IDE將爲您自動補全並添加新的import語句。除非開發人員專門檢查以確保其import語句僅導入正確的視圖,否則沒有安全的方法來驗證這不會引起運行時問題。

分析

  • 空安全(Null-safe): 通常情況下,它是空安全的。但是,如果視圖ID在其他佈局中也存在/缺失,那麼需要開發人員顯示的使用操作符"?"或者在使用前判空。開發人員可能使用了其他佈局中的view導致NullPointerException
  • 樣板代碼(Boilerplate Code): 沒有樣板代碼因爲擴展方法生成了。只需要在build.gradle中使用android-kotlin-extension插件。
  • 語言(Languages): 僅支持Kotlin

——————————————————————————————————

Data Binding

Data Binding庫是一個Support庫,使您可以使用聲明式樣式(而不是通過編程方式)將佈局中的UI元素綁定到應用程序中的數據源。

Data Binding在功能上比其他方法優越得多,因爲它不僅爲您提供類型安全和null安全的視圖引用,而且還允許您直接在XML佈局內使用視圖映射數據。

您必須手動轉換佈局來支持Data Binding通過嵌套在標籤中。
在這裏插入圖片描述
使用Data Binding最大的優點是,它使開發人員甚至無需訪問Java / Kotlin文件中的視圖即可將數據與XML中的視圖進行映射。您也可以使用雙向綁定來更新XML或數據值,而無需任何listener或callback。

分析

  • 樣板代碼(Boilerplate Code): 要求每個佈局文件都嵌套在標籤內。而且,您還必須創建自動生成的綁定類的實例,並將其填充到您的Activity或Fragment中。
  • 構建時間(Build Time): 由於生成佈局對應的類文件而增加了構建時間。通常,它很慢,因爲您必須手動點擊“Make”按鈕來爲佈局更新/生成新的類。
  • 語言(Languages): 支持Java和Kotlin

——————————————————————————————————

View Binding

最近,ViewBinding作爲Data Binding庫的排序子集在Android Studio 3.6中引入。由於不需要註解處理,因此可以縮短構建時間。它不需要因爲嵌套標籤而導致過多關注佈局文件,默認情況下,它適用所有佈局文件。

它與Data Binding唯一的區別在於,該綁定僅用於視圖引用。它不執行任何數據映射或雙向數據綁定。

如果您只是在尋找一種從佈局文件獲取視圖的好方法,則可以使用ViewBinding代替其他選項。

這僅適用於Android Studio 3.6或更高版本。您可以通過將其添加到app的build.gradle文件中來啓用它。
在這裏插入圖片描述

然後,Android Studio將爲您的所有佈局文件生成View Binding類。您可以使用這些類在“Activity”或“Fragment”中進行填充,就像在Data Binding中所做的那樣。
在這裏插入圖片描述

如果要跳過某些佈局文件,可以通過在佈局文件中添加 *tools:viewBindingIgnore =“ true”*來實現。

分析

  • 樣板代碼(Boilerplate Code): 沒有樣板代碼,因爲View Binding類是自動生成的。它只需要在build.gradle中啓用View Binding。
  • 構建時間(Build Time): 對構建速度沒有影響。 View Binding 旨在解決使用Data Binding 相關的性能問題,因此不會對構建速度產生負面影響。
  • 語言(Languages): 支持Java和Kotlin

——————————————————————————————————

是時候做決定了

觀察了所有方法及其分析,View Binding是目前可使用的最佳方法。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章