View Binding(視圖綁定)
視圖綁定是一項(xiàng)功能卒暂,可讓你更輕松地編寫與視圖交互的代碼。在模塊中啟用視圖綁定后撞叽,它會為該模塊中存在的每個 XML 布局文件生成一個 綁定類姻成。綁定類的實(shí)例包含對在相應(yīng)布局中具有 ID 的所有視圖的直接引用。
在大多數(shù)情況下愿棋,View Binding會替換findViewById.
設(shè)置
視圖綁定在一個模塊一個模塊的基礎(chǔ)上啟用科展。要在模塊中啟用視圖綁定,請?jiān)?strong>Module級build.gradle文件中將viewBinding構(gòu)建選項(xiàng)設(shè)置為true糠雨,如下例所示:
android {
...
buildFeatures {
viewBinding true
}
}
如果你那個布局文件不需要生成綁定類(不想用這個功能)才睹,請將該 tools:viewBindingIgnore="true" 屬性添加到該布局文件的根視圖中:
<LinearLayout
...
tools:viewBindingIgnore="true" >
...
</LinearLayout>
使用
如果為Module啟用了視圖綁定,則會為Module包含的每個 XML 布局文件生成一個綁定類。每個綁定類都包含對根視圖和所有具有 ID 的視圖的引用琅攘。綁定類的名稱是通過將 XML 文件的名稱轉(zhuǎn)換為 Pascal 大小寫并在末尾添加Binding一詞來生成的垮庐。
例如,給定一個名為activity_progressbar.xml的布局文件:
<LinearLayout>
...
<ProgressBar
android:id="@+id/progress_1"/>
<ProgressBar
style="@android:style/Widget.ProgressBar.Small" />
<ProgressBar
android:id="@+id/progress_3"/>
<ProgressBar
style="@android:style/Widget.ProgressBar.Inverse" />
<ProgressBar
android:id="@+id/progress_5"/>
<ProgressBar
style="@android:style/Widget.ProgressBar.Large.Inverse" />
...
</LinearLayout>
布局文件中有6個ProgressBar坞琴,只有3個ProgressBar設(shè)置了android:id哨查。
生成的綁定類稱為ActivityProgressbarBinding。這個類有3個字段:progress_1剧辐、progress_3寒亥、progress_5。另外3個在布局具有沒有ID荧关,所以在綁定類沒有提及溉奕。
每個綁定類還包含一個getRoot()方法,為相應(yīng)布局文件的根視圖提供直接引用忍啤。在這個例子中加勤,類中的getRoot()方法ActivityProgressbarBinding返回 LinearLayout根視圖。
在Activity中使用視圖綁定
要設(shè)置用于Activity的綁定類的實(shí)例同波,請?jiān)贏ctivity的onCreate()方法中執(zhí)行以下步驟 :
- 1.調(diào)用inflate()包含在生成的綁定類中的靜態(tài)方法胸竞。這會為要使用的活動創(chuàng)建綁定類的實(shí)例。
- 2.通過調(diào)用getRoot()方法獲取對根視圖的引用参萄。
- 3.將根視圖傳遞給以 setContentView() 使其成為屏幕上的活動視圖卫枝。
實(shí)例如下:
private ActivityProgressbarBinding activityProgressbarBinding;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityProgressbarBinding = ActivityProgressbarBinding.inflate(getLayoutInflater());
// View view = activityProgressbarBinding.getRoot();
// setContentView(view);
//一步到位也可以
setContentView(activityProgressbarBinding.getRoot());
//使用綁定類的實(shí)例來引用任何View(XML中必須添加id)
activityProgressbarBinding.progress1.setMax(120);
activityProgressbarBinding.progress3.setProgress(20);
}
在Fragment中使用視圖綁定
要設(shè)置與Fragment一起使用的綁定類的實(shí)例,請?jiān)贔ragment的onCreateView()方法中執(zhí)行以下步驟 :
- 1.調(diào)用inflate()包含在生成的綁定類中的靜態(tài)方法讹挎。這會為要使用的Fragment創(chuàng)建綁定類的實(shí)例校赤。
- 2.通過調(diào)用getRoot()方法獲取對根視圖的引用。
- 3.從onCreateView()方法返回根視圖筒溃,使其成為屏幕上的活動視圖马篮。
注意: 該inflate()方法要求你傳入布局充氣器。如果布局已經(jīng)inflated怜奖,你可以改為調(diào)用綁定類的靜態(tài)bind()方法浑测。
實(shí)例如下:
private FragmentMineBinding binding;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = FragmentMineBinding.inflate(inflater,container,false);
View view = binding.getRoot();
return view;
}
@Override
public void onDestroy() {
super.onDestroy();
binding = null;
}
提供不同配置的提示
當(dāng)你跨多個配置聲明視圖時(shí),有時(shí)根據(jù)特定布局使用不同的視圖類型是有意義的歪玲。例如:
# in res/layout/example.xml
<TextView android:id="@+id/user_bio" />
# in res/layout-land/example.xml
<EditText android:id="@+id/user_bio" />
在這種情況下迁央,你可能希望生成的類公開一個userBio type字段TextView,因?yàn)門extView是公共基類滥崩。不幸的是岖圈,由于技術(shù)限制,視圖綁定代碼生成器無法做出這個決定钙皮,View而是簡單地生成一個字段蜂科。這將需要稍后使用binding.userBio as TextView.
為了解決這個限制顽决,視圖綁定支持一個tools:viewBindingType 屬性,允許你告訴編譯器在生成的代碼中使用什么類型导匣。在上面的示例中才菠,你可以使用此屬性使編譯器將字段生成為TextView:
# in res/layout/example.xml (unchanged)
<TextView android:id="@+id/user_bio" />
# in res/layout-land/example.xml
<EditText android:id="@+id/user_bio" tools:viewBindingType="TextView" />
在另一個示例中,假設(shè)你有兩個布局贡定,其中一個包含 BottomNavigationView赋访,另一個包含 NavigationRailView。這兩個類NavigationBarView都包含了大部分實(shí)現(xiàn)細(xì)節(jié)厕氨。如果你的代碼不需要確切知道當(dāng)前布局中存在哪個子類进每,你可以使用tools:viewBindingType將生成的類型設(shè)置為NavigationBarView在兩個布局中:
# in res/layout/navigation_example.xml
<BottomNavigationView android:id="@+id/navigation" tools:viewBindingType="NavigationBarView" />
# in res/layout-w720/navigation_example.xml
<NavigationRailView android:id="@+id/navigation" tools:viewBindingType="NavigationBarView" />
注意: 視圖綁定在生成代碼時(shí)無法驗(yàn)證此屬性的值汹粤。為避免編譯時(shí)和運(yùn)行時(shí)錯誤命斧,該值必須滿足以下條件:
- 該值必須是繼承自android.view.View的類。
- 該值必須是放置它的標(biāo)簽的超類嘱兼。例如国葬,以下值將不起作用:
<!-- ImageView is not related to TextView -->
<TextView tools:viewBindingType="ImageView" />
<!-- Button is not a superclass of TextView -->
<TextView tools:viewBindingType="Button" />
- 最終類型必須在所有配置中一致解析。
與 findViewById 的區(qū)別
與使用相比芹壕,View binding具有重要的優(yōu)勢findViewById:
- 空安全:由于視圖綁定創(chuàng)建了對視圖的直接引用汇四,因此不存在因視圖 ID 無效而導(dǎo)致空指針異常的風(fēng)險(xiǎn)。此外踢涌,當(dāng)視圖僅存在于布局的某些配置中時(shí)通孽,綁定類中包含其引用的字段會標(biāo)記為 @Nullable。
- 類型安全:每個綁定類中的字段的類型與其在 XML 文件中引用的視圖相匹配睁壁。這意味著沒有類轉(zhuǎn)換異常的風(fēng)險(xiǎn)背苦。
這些差異意味著你的布局和代碼之間的不兼容性將導(dǎo)致你的構(gòu)建在編譯時(shí)而不是運(yùn)行時(shí)失敗。
與數(shù)據(jù)綁定的比較
View binding和Data Binding都生成可用于直接引用視圖的綁定類潘明。但是行剂,View binding旨在處理更簡單的用例,并提供以下優(yōu)于Data Binding的好處:
- 更快的編譯: 視圖綁定不需要注釋處理钳降,因此編譯時(shí)間更快厚宰。
- 易用性: 視圖綁定不需要特別標(biāo)記的 XML 布局文件,因此在您的應(yīng)用程序中采用它的速度更快遂填。在模塊中啟用視圖綁定后铲觉,它會自動應(yīng)用于該模塊的所有布局。
相反吓坚,與數(shù)據(jù)綁定相比备燃,視圖綁定有以下限制:
- 視圖綁定不支持布局變量或布局表達(dá)式,因此它不能用于直接從 XML 布局文件聲明動態(tài) UI 內(nèi)容凌唬。
布局變量或布局表達(dá)式: 表達(dá)式語言允許您編寫處理由視圖調(diào)度的事件的表達(dá)式并齐。數(shù)據(jù)綁定庫會自動生成將布局中的視圖與數(shù)據(jù)對象綁定所需的類漏麦。
- 視圖綁定不支持雙向數(shù)據(jù)綁定。
雙向數(shù)據(jù)綁定: 單向數(shù)據(jù)綁定况褪,你可以在屬性上設(shè)置一個值并設(shè)置一個對該屬性更改做出反應(yīng)的listener撕贞,雙向數(shù)據(jù)綁定提供了此過程的快捷方式。
由于這些考慮测垛,在某些情況下最好在項(xiàng)目中同時(shí)使用View Binding和Data Binding捏膨。你可以在需要高級功能的布局中使用Data Binding,而在不需要高級功能的布局中使用View Binding食侮。
注意: 在很多情況下号涯,視圖綁定可以提供與數(shù)據(jù)綁定相同的好處,但實(shí)現(xiàn)更簡單锯七,性能更好链快。如果您主要使用數(shù)據(jù)綁定來替換findViewById() 調(diào)用,使用視圖綁定更佳眉尸。
以上就是View Binding(視圖綁定)的全部內(nèi)容域蜗,希望對你有所幫助。以后有條件了咱們再學(xué)習(xí)一下了Data Binding(數(shù)據(jù)綁定)噪猾。