[TOC]
# 1. 說明
視圖綁定在大多數情況下,視圖綁定會替代`findViewById`。而其實我們自己也可以定義一些注解,通過反射來完成對應的`findViewById`工作,比如`Xutils`和`ButterKnife`中都提供了這個功能。使用的時候比較簡單,比如:
```java
@BindView(R.id.id_test)
TextView tvTest;
```
但是上面兩種使用注解及反射方式的查找控件實例的方式本質上都是調用`findViewById`自身。`Google`在`Jetpack`中推出視圖綁定,首先看看二者有何不同。
## 1.1 與 findViewById 的區別
* **Null 安全**:由于視圖綁定會創建對視圖的直接引用,因此不存在因視圖 `ID` 無效而引發 Null 指針異常的風險。此外,如果視圖僅出現在布局的某些配置中,則綁定類中包含其引用的字段會使用`@Nullable`標記。
* **類型安全**:每個綁定類中的字段均具有與它們在 `XML` 文件中引用的視圖相匹配的類型。這意味著不存在發生類轉換異常的風險。
# 2. 使用
## 2.1 環境配置
首先檢查一下`Android Studio`的版本,視圖綁定在[Android Studio 3.6 Canary 11 及更高版本](https://developer.android.google.cn/studio/preview)中可用。
要在某個模塊中啟用視圖綁定,請將`viewBinding`元素添加到其`build.gradle`文件中,如下例所示:
~~~
android {
...
viewBinding {
enabled = true
}
}
~~~
如果您希望在生成綁定類時忽略某個布局文件,請將`tools:viewBindingIgnore="true"`屬性添加到相應布局文件的根視圖中:
~~~
<LinearLayout? ? ? ? ? ?
...? ? ? ? ? ?
tools:viewBindingIgnore="true" >? ? ? ?
...? ?
</LinearLayout>? ?
~~~
## 2.1 用法
為某個模塊啟用視圖綁定功能后,系統會為該模塊中包含的每個 `XML` 布局文件生成一個綁定類。每個綁定類均包含對根視圖以及具有 `ID` 的所有視圖的引用。系統會通過以下方式生成綁定類的名稱:將 `XML` 文件的名稱轉換為駝峰式大小寫,并在末尾添加“Binding”一詞。
例如,假設某個布局文件的名稱為`result_profile.xml`:
~~~
<LinearLayout ... >
<TextView android:id="@+id/name" />
<ImageView android:cropToPadding="true" />
<Button android:id="@+id/button" />
</LinearLayout>
~~~
所生成的綁定類的名稱就為`ResultProfileBinding`。此類具有兩個字段:一個是名為`name`的`TextView`,另一個是名為`button`的`Button`。該布局中的`ImageView`沒有 `ID`,因此綁定類中不存在對它的引用。
每個綁定類還包含一個`getRoot()`方法,用于為相應布局文件的根視圖提供直接引用。在此示例中,`ResultProfileBinding`類中的`getRoot()`方法會返回`LinearLayout`根視圖。
### 2.1.1 在 Activity 中使用視圖綁定
請在 Activity 的`onCreate()`方法中執行以下步驟:
1. 調用生成的綁定類中包含的靜態`inflate()`方法。此操作會創建該綁定類的實例以供 Activity 使用。
2. 通過調用`getRoot()`方法或使用Kotlin 屬性語法獲取對根視圖的引用。
3. 將根視圖傳遞到`setContentView()`,使其成為屏幕上的活動視圖。
~~~kotlin
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// R.layout.activity_main
// ViewBinding
binding = ActivityMainBinding.inflate(layoutInflater)
val rootView = binding.root
setContentView(rootView)
// TextView -> id=@+id/textView
binding.textView
// Button -> id=@+id/update
binding.update
}
~~~
### 2.1.2 在 Fragment 中使用視圖綁定
請在 Fragment 的[`onCreateView()`](https://developer.android.google.cn/reference/kotlin/androidx/fragment/app/Fragment#oncreateview)方法中執行以下步驟:
1. 調用生成的綁定類中包含的靜態`inflate()`方法。此操作會創建該綁定類的實例以供 Fragment 使用。
2. 通過調用`getRoot()`方法或使用Kotlin 屬性語法獲取對根視圖的引用。
3. 從`onCreateView()`方法返回根視圖,使其成為屏幕上的活動視圖。
~~~kotlin
class BlankFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
private var binding: FragmentBlankBinding? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// R.layout.fragment_blank
binding = FragmentBlankBinding.inflate(inflater, container, false)
val rootView = binding?.root
return rootView
}
override fun onDestroy() {
super.onDestroy()
binding = null
}
}
~~~