檢視區塊繫結 Android Jetpack 的一部分。
檢視區塊繫結功能可讓您更輕鬆地編寫與檢視區塊互動的程式碼。在模組中啟用檢視區塊繫結後,系統會為該模組中的每個 XML 版面配置檔案產生繫結類別。繫結類別的例項包含所有檢視區塊 (在對應的版面配置中有 ID 的檢視區塊) 的直接參照內容。
在大多數情況下,檢視區塊繫結會取代 findViewById。
設定
檢視區塊繫結是以模組為單位啟用。如要在模組中啟用檢視畫面繫結,請在模組層級 build.gradle 檔案中,將 viewBinding 建構選項設為 true,如以下範例所示:
Groovy
android { ... buildFeatures { viewBinding true } }
Kotlin
android { ... buildFeatures { viewBinding = true } }
如要在產生繫結類別時忽略版面配置檔案,請將 tools:viewBindingIgnore="true" 屬性新增至該版面配置檔案的根層級檢視畫面:
<LinearLayout
...
tools:viewBindingIgnore="true" >
...
</LinearLayout>
用量
如果模組已啟用檢視區塊繫結,系統會為模組包含的每個 XML 版面配置檔案產生繫結類別。每個繫結類別都包含根檢視區塊和所有具有 ID 的檢視區塊的參照。系統會透過以下方式產生繫結類別的名稱:將 XML 檔案的名稱轉換為 Pascal 命名法,並在結尾處加上字詞「Binding」。
舉例來說,假設版面配置檔案 result_profile.xml 包含下列內容:
<LinearLayout ... >
<TextView android:id="@+id/name" />
<ImageView android:cropToPadding="true" />
<Button android:id="@+id/button"
android:background="@drawable/rounded_button" />
</LinearLayout>
產生的繫結類別稱為 ResultProfileBinding。這個類別有兩個欄位:名為 name 的 TextView,以及名為 button 的 Button。版面配置中的 ImageView 沒有 ID,因此繫結類別中沒有對其的參照。
每個繫結類別也包含 getRoot() 方法,可直接參照對應版面配置檔案的根層級檢視畫面。在本範例中,ResultProfileBinding 類別中的 getRoot() 方法會傳回 LinearLayout 根層級檢視畫面。
以下各節示範如何在活動和片段中使用產生的繫結類別。
在活動中使用檢視繫結
如要設定繫結類別的例項,以便與活動搭配使用,請在活動的 onCreate() 方法中執行下列步驟:
- 呼叫產生的繫結類別中包含的靜態
inflate()方法。這會建立繫結類別的例項,供活動使用。 - 呼叫
getRoot()方法或使用 Kotlin 屬性語法,取得根層級檢視畫面的參照。 - 將根層級檢視區塊傳遞至
setContentView(),使其成為畫面上的有效檢視區塊。
相關步驟如以下範例所示︰
Kotlin
private lateinit var binding: ResultProfileBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ResultProfileBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
}
Java
private ResultProfileBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ResultProfileBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
}
現在,您可以使用繫結類別的例項來參照任何檢視畫面:
Kotlin
binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }
Java
binding.name.setText(viewModel.getName());
binding.button.setOnClickListener(new View.OnClickListener() {
viewModel.userClicked()
});
在片段中使用檢視繫結
如要設定繫結類別的例項,以便與片段搭配使用,請在片段的 onCreateView() 方法中執行下列步驟:
- 呼叫產生的繫結類別中包含的靜態
inflate()方法。這會建立繫結類別的例項,供片段使用。 - 呼叫
getRoot()方法或使用 Kotlin 屬性語法,取得根層級檢視畫面的參照。 - 從
onCreateView()方法傳回根層級檢視畫面,使其成為畫面上的有效檢視畫面。
Kotlin
private var _binding: ResultProfileBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = ResultProfileBinding.inflate(inflater, container, false)
val view = binding.root
return view
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
Java
private ResultProfileBinding binding;
@Override
public View onCreateView (LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
binding = ResultProfileBinding.inflate(inflater, container, false);
View view = binding.getRoot();
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
現在,您可以使用繫結類別的例項來參照任何檢視畫面:
Kotlin
binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }
Java
binding.name.setText(viewModel.getName());
binding.button.setOnClickListener(new View.OnClickListener() {
viewModel.userClicked()
});
為不同設定提供提示
在多個設定中宣告檢視畫面時,有時可以根據特定版面配置使用不同的檢視畫面類型。以下程式碼片段為範例:
# in res/layout/example.xml
<TextView android:id="@+id/user_bio" />
# in res/layout-land/example.xml
<EditText android:id="@+id/user_bio" />
在這種情況下,您可能會預期產生的類別會公開 TextView 類型的欄位 userBio,因為 TextView 是常見的基礎類別。由於技術限制,檢視繫結程式碼產生器無法判斷這一點,而是產生 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" />
再舉一個例子,假設您有兩個版面配置,一個包含 BottomNavigationView,另一個包含 NavigationRailView。這兩個類別都會擴充 NavigationBarView,其中包含大部分的實作詳細資料。如果程式碼不需要確切知道目前版面配置中存在哪個子類別,您可以使用 tools:viewBindingType,將兩個版面配置中產生的類型設為 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" />
產生程式碼時,檢視繫結無法驗證這個屬性的值。為避免編譯時間和執行階段錯誤,值必須符合下列條件:
- 值必須是繼承自
android.view.View的類別。 這個值必須是標記的父類別。舉例來說,下列值無效:
<TextView tools:viewBindingType="ImageView" /> <!-- ImageView is not related to TextView. --> <TextView tools:viewBindingType="Button" /> <!-- Button is not a superclass of TextView. -->最終類型必須在所有設定中一致解析。
與 findViewById 的差異
與使用 findViewById 相比,檢視繫結具有以下重要優點:
- 空值安全:由於檢視區塊繫結會建立檢視區塊的直接參照,因此不會有無效檢視區塊 ID 造成空值指標例外狀況的風險。此外,如果檢視畫面僅出現在版面配置的某些設定中,則繫結類別中包含其參照的欄位會標示為
@Nullable。 - 類型安全:每個繫結類別中的欄位類型,都與 XML 檔案中參照的檢視區塊相符。這表示不會有類別轉換例外狀況的風險。
這些差異表示版面配置和程式碼之間不相容,導致建構作業在編譯時間失敗,而不是在執行階段失敗。
與資料繫結比較
檢視繫結和資料繫結都會產生繫結類別,可用於直接參照檢視畫面。不過,檢視畫面繫結旨在處理較簡單的用途,與資料繫結相比,具有下列優點:
- 編譯速度更快:檢視區塊繫結不需要處理註解,因此編譯時間更快。
- 易於使用:檢視區塊繫結不需要特別標記的 XML 版面配置檔案,因此可更快在應用程式中採用。在模組中啟用檢視畫面繫結後,系統會自動將其套用至該模組的所有版面配置。
另一方面,與資料繫結相比,檢視畫面繫結有下列限制:
- 檢視畫面繫結不支援版面配置變數或版面配置運算式,因此無法用於直接從 XML 版面配置檔案宣告動態 UI 內容。
- 檢視區塊繫結不支援雙向資料繫結。
基於上述考量,在某些情況下,最好在專案中同時使用檢視畫面繫結和資料繫結。您可以在需要進階功能的版面配置中使用資料繫結,並在不需要進階功能的版面配置中使用檢視繫結。
其他資源
如要進一步瞭解檢視畫面繫結,請參閱下列其他資源:
網誌
影片
為您推薦
- 注意:系統會在 JavaScript 關閉時顯示連結文字
- 從 Kotlin 合成項目遷移至 Jetpack 檢視區塊繫結
- 版面配置與繫結的運算式
- 應用程式架構:UI 層 - 入門指南 - Android 開發人員