ViewBinding 的出現就是爲了替代 findViewById 的。以前我們寫完佈局後就要在代碼中使用 findViewById 方法找到 xml 文件中對應的 view ,這樣耗時費力,還有可能會出錯,比如 view 跟 id 不一致等等,奇奇怪怪的問題,畢竟人力和時間有限,這種簡單繁雜的工作直接交給 IDE 去做不是更好,它們做的檢測工作肯定比人來更精準。
配置
Android Studio 3.6 Canary 11 之後的版本都支持使用ViewBinding這個功能模塊了,只需要在 app/build.gradle 文件添加如下代碼即可:
android {
...
viewBinding {
enabled = true
}
}
Android Studio 4.0 後改成了這樣:
android {
...
buildFeatures {
viewBinding = true
}
}
通過上面的配置後,我們工程目錄下的 xml 佈局文件,就會生成對應的 Binding 類。例如:activity_main.xml 就會生成 ActivityMainBinding 類。這個類就會完成 findViewById 的工作。
當然,如果我們不想我們的 xml 文件生成 Binding 類,我們可以在 xml 佈局文件中根 view 寫入
tools:viewBindingIgnore="true"
Binding 類生成的路徑在build/generated/data_binding_base_class_source_out/debug/out/com/xxx/yyy/databinding/
目錄下。
我們來看下 ViewBinding 幫我們生成的類的代碼結構是怎麼樣的。
public final class ActivityMainBinding implements ViewBinding {
@NonNull
private final ConstraintLayout rootView;
@NonNull
public final TextView idText;
private ActivityMainBinding(@NonNull ConstraintLayout rootView, @NonNull TextView idText) {
this.rootView = rootView;
this.idText = idText;
}
@NonNull
public ConstraintLayout getRoot() {
return this.rootView;
}
@NonNull
public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater) {
return inflate(inflater, (ViewGroup)null, false);
}
@NonNull
public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater, @Nullable ViewGroup parent, boolean attachToParent) {
View root = inflater.inflate(2131361820, parent, false);
if (attachToParent) {
parent.addView(root);
}
return bind(root);
}
@NonNull
public static ActivityMainBinding bind(@NonNull View rootView) {
int id = 2131165279;
TextView idText = (TextView)rootView.findViewById(id);
if (idText == null) {
String missingId = rootView.getResources().getResourceName(id);
throw new NullPointerException("Missing required view with ID: ".concat(missingId));
} else {
return new ActivityMainBinding((ConstraintLayout)rootView, idText);
}
}
}
Android Studio 主要幫我們實現了3個方法,getRoot, inflate, bind 。最重要的就是 bind 方法了。這個方法纔是真正實現 findViewById 的地方。
用法
- Activity 中
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.idText.setText("ViewBinding");
}
- Fragment 中
inflate 方法
ActivityMainBinding binding;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = FragmentMainBinding.inflate(inflater, container, false);
binding.idText.setText("Fragment");
return binding.getRoot();
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
或者 bind 方法
FragmentMainBinding binding;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding = FragmentMainBinding.bind(view);
binding.idText.setText("Fragment");
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
同類競品
- ButterKnife
通過註解實現 findViewById。
- Kotlin Android Extensions
通過 Kotlin 語言特性底層實現 findViewById。
- DataBinding
通過 annotation processor 實現,會影響工程的構建速度。
優點
-
Null 安全
-
類型安全
總結
ViewBinding 總的來說就是替換 findViewById 的。可以節省我們的開發時間,提高效率。從以前的人工查找綁定,改爲 Android Studio 幫助我們查找綁定並生成對應的類。從而幫助開發人員從繁瑣的 view 查找綁定中抽身出來,做更有意義的事情。