View 繫結
Android Jetpack 的一部分。
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
檢視區塊繫結功能可讓您更輕鬆地編寫與檢視區塊互動的程式碼。在模組中啟用檢視區塊繫結後,系統會為該模組中的每個 XML 版面配置檔案產生繫結類別。凡是在對應版面配置中具有 ID 的檢視區塊,繫結類別的例項都會包含指向這些檢視區塊的直接參照。
在大多數情況下,檢視畫面繫結會取代 findViewById
。
設定
檢視區塊繫結會依模組逐一啟用。如要在模組中啟用檢視畫面繫結,請在模組層級 build.gradle
檔案中將 viewBinding
建構選項設為 true
,如以下範例所示:
android { ... buildFeatures { viewBinding true } }
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()
,讓它成為螢幕上的有效檢視區塊。
相關步驟如以下範例所示:
private lateinit var binding: ResultProfileBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ResultProfileBinding.inflate(layoutInflater) val view = binding.root setContentView(view) }
private ResultProfileBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ResultProfileBinding.inflate(getLayoutInflater()); View view = binding.getRoot(); setContentView(view); }
您現在可以使用繫結類別的例項,參照任何檢視畫面:
binding.name.text = viewModel.name binding.button.setOnClickListener { viewModel.userClicked() }
binding.name.setText(viewModel.getName()); binding.button.setOnClickListener(new View.OnClickListener() { viewModel.userClicked() });
在片段中使用檢視繫結
如要設定繫結類別的例項,以便與片段搭配使用,請在片段的 onCreateView()
方法中執行下列步驟:
- 呼叫產生繫結類別中包含的靜態
inflate()
方法。這會為片段建立繫結類別的例項。 - 呼叫
getRoot()
方法或使用 Kotlin 屬性語法,取得根檢視區塊的參照。 - 從
onCreateView()
方法傳回根檢視區塊,將其設為螢幕上的有效檢視區塊。
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 }
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; }
您現在可以使用繫結類別的例項,參照任何檢視畫面:
binding.name.text = viewModel.name binding.button.setOnClickListener { viewModel.userClicked() }
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 檔案中參照的檢視區塊相符。也就是說,不會發生類別轉換例外狀況。
這些差異表示版面配置和程式碼不相容,導致建構作業在編譯時間而非執行階段失敗。
與資料繫結的比較
檢視畫面繫結和資料繫結都會產生繫結類別,您可以使用這些繫結類別直接參照檢視畫面。不過,檢視區塊繫結可處理較簡單的用途,且相較於資料繫結,可提供下列優點:
- 編譯速度更快:View 繫結不需要註解處理,因此編譯時間更快。
- 使用簡便:檢視區塊繫結不需要特別標記的 XML 版面配置檔案,因此可更快速地在應用程式中採用。在模組中啟用檢視畫面繫結後,系統會自動將其套用至該模組的所有版面配置。
另一方面,與資料繫結相比,檢視繫結有下列限制:
- 檢視繫結不支援版面配置變數或版面配置運算式,因此無法用於直接透過 XML 版面配置檔案宣告動態 UI 內容。
- 檢視繫結不支援雙向資料繫結。
基於這些考量,在某些情況下,建議您在專案中同時使用檢視繫結和資料繫結。您可以在需要進階功能的版面配置中使用資料繫結,也可以在不需要進階功能的版面配置中使用檢視畫面繫結。
其他資源
如要進一步瞭解 View Binding,請參閱下列其他資源:
網誌
影片
為你推薦
從 Kotlin 合成項目遷移至 Jetpack 檢視區塊繫結
Discover the latest app development tools, platform updates, training, and documentation for developers across every Android device.
版面配置與繫結的運算式
Discover the latest app development tools, platform updates, training, and documentation for developers across every Android device.
應用程式架構:UI 層 - 入門指南 - Android 開發人員
探索此應用程式層程式庫上的應用程式架構指南,以瞭解建構環境、Android Studio 支援資料繫結等項目。