View BindingはViewを操作するコードを簡単に記述できる機能で、XMLレイアウトごとBindすることができます。
View Binding が「大概のケース」でfindViewByIdの後継として使えます。例外もありまったりしますが…
2021.1.1
View Binding の設定
XMLレイアウトファイルからIDを読みだして、findViewById を使ってコードと結びつけるのが昔からの方法です。
findViewById の不都合なことがある場合として、
- nullable
- findViewByIdの戻り値はnullableでタイミングが悪いあるいは間違ったidを読んでnullなる可能性が潜んでいる
 
- 型の指定
- 型安全ではないので型を指定して呼び出す必要がある
 
- 紐づけが面倒
- たくさんの紐づけをする場合に顕著に表れる冗長的な作業、バグの元
 
等があります。1つ2つであればfindViewById は簡単ですが大きなプロジェクトでは
View Binding が推奨されるでしょう。
 
Kotlinでは以下で説明しています。
 
build.gradleの設定
build.gradle ファイルに viewBinding 要素を追加し true にします。
同じ名前のファイルが2つあり、プロジェクト用(Project: xxx)とモジュール用(Module: xxx.app)で、モジュール用を使用します。
ターゲットのAPIレベルやライブラリーの情報が設定されます。
 
build.gradle(Module: xxx)
| 1 2 3 4 5 6 7 8 | ... android {     ...     buildFeatures {          viewBinding true      } } ... | 
この他に以下のような設定でも通りました。
| 1 2 3 | viewBinding {     enabled = true } | 
あるいは、gradle.properties に以下のような記述を追加しても可能です
| 1 | android.defaults.buildfeatures.viewbinding=true | 
設定後に「Sync Now」を実行するのを忘れずに
また反映されるのに時間がかかることもあります
![[Android] findViewByIdの代わりにView Bindingを使ってみた 1x1.trans - [Android] findViewByIdの代わりにView Bindingを使ってみた](https://akira-watson.com/wp-content/themes/simplicity2/images/1x1.trans.gif)
Binding Classを生成
プロジェクトのレイアウトファイル毎にViewBinding Class を作成します。
| 1 2 3 | package com.example.testbutton ... import com.example.testbutton.databinding.ActivityMainBinding | 
例えば、activity_main.xml の場合はactivity_mainをキャメルケースに変換して、package name とdatabindingを頭に付け、末尾に「Binding」を追加することで生成します。
[package name].databinding.[XMLレイアウトファイル名から]Binding
| activity_main.xml | >> | ActivityMainBinding | 
| sub_layout.xml | >> | SubLayoutBinding | 
| main.xml | >> | MainBinding | 
activity_main.xmが以下のような場合
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout     ...     >     <TextView         android:id="@+id/text_view"         ... />     <ImageView         android:src="@drawable/image"         ... />     <EditText         android:id="@+id/edittext"         .../>     <Button         android:id="@+id/button"         ... /> </androidx.constraintlayout.widget.ConstraintLayout> | 
Binding Class のActivityMainBindingには3つのフィールドがあります。
- text_view という名前の TextView フィールド
- edittext という名前の EditText フィールド
- button という名前の Button フィールド
bindingで以下のように参照できます
| 1 2 3 4 5 | binding.textView... binding.edittext... binding.button... | 
ImageViewには ID が無いので、このバインディングクラス内にそのビューへの参照は存在しません。
Binding Classには getRoot() メソッドも含まれるので、レイアウトファイルの
root viewを直接参照できます。上記のActivityMainBindingクラスでは getRoot() により
constraintlayout の root view を返します。
Activityへの実装
MainActivityの onCreate() で次の手順を実施
- Binding Classのインスタンスを生成
- Binding Classに含まれる静的 inflate() メソッドを呼び出し生成
 
- getRoot()を呼び出してroot viewへの参照を取得
- root view を setContentView() に渡す
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // View Binding Class のインスタンス // lateinit で宣言し初期化タイミングを onCreate() まで遅らせる private ActivityMainBinding binding; @Override protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     // bindingのイニシャライズ     // Binding Classに含まれる静的 inflate() メソッドを呼び出す     binding = ActivityMainBinding.inflate(getLayoutInflater());     // root view への参照を取得     View view = binding.getRoot();     // view をsetContentView()にセット     setContentView(view)     binding.button.setOnClickListener(new View.OnClickListener() {         ...     }); } | 
冗長なので短縮できます
| 1 2 |  // view をsetContentView()にセット  setContentView(binding.getRoot()); | 
以上で設定ができました。
サンプルコード
ButtonとTextViewを使ったJavaコードのサンプルをView Bindingにしてみます。
 
MainActivity.java
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | //package com.example.testbuttonviewbinding; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import com.example.testbuttonviewbinding.databinding.ActivityMainBinding; public class MainActivity extends AppCompatActivity {     private ActivityMainBinding binding;     private boolean buttonTap = false;     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState); //        setContentView(R.layout.activity_main);         binding = ActivityMainBinding.inflate(getLayoutInflater());         setContentView(binding.getRoot());         binding.button.setOnClickListener( v -> {             // flagがtrueの時             if (buttonTap) {                 binding.textView.setText(R.string.hello);                 buttonTap = false;             }             // flagがfalseの時             else {                 binding.textView.setText(R.string.world);                 buttonTap = true;             }         });     } } | 
 
activity_main.xml
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout     xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:padding="20dp"     tools:context=".MainActivity">     <TextView         android:id="@+id/text_view"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:text="@string/hello"         android:textSize="50sp"         android:textColor="#00ff00"         app:layout_constraintBottom_toBottomOf="parent"         app:layout_constraintLeft_toLeftOf="parent"         app:layout_constraintRight_toRightOf="parent"         app:layout_constraintTop_toTopOf="parent"         app:layout_constraintVertical_bias="0.4" />     <Button         android:id="@+id/button"         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:text="@string/button"         android:textSize="20sp"         app:layout_constraintBottom_toBottomOf="parent"         app:layout_constraintLeft_toLeftOf="parent"         app:layout_constraintRight_toRightOf="parent"         app:layout_constraintTop_toTopOf="parent"         app:layout_constraintVertical_bias="0.6" /> </androidx.constraintlayout.widget.ConstraintLayout> | 
 
strings.xml
| 1 2 3 4 5 6 | <resources>     <string name="app_name">TestButtonViewBinding</string>     <string name="hello">Hello</string>     <string name="world">World</string>     <string name="button">Button</string> </resources> | 
 
build.gradle
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | plugins {     id 'com.android.application' } android {     ...     buildFeatures {         viewBinding true     } } dependencies {     ... } | 
References:
ビュー バインディング – Android Developers
findViewById
BuildFeatures | Android Developers
![[Android] findViewByIdの代わりにView Bindingを使ってみた cat44 00 100x100 - [Android] findViewByIdの代わりにView Bindingを使ってみた](https://akira-watson.com/wp-content/uploads/2019/07/cat44_00-100x100.jpg)
![[Android] findViewByIdの代わりにView Bindingを使ってみた test button 00 100x100 - [Android] findViewByIdの代わりにView Bindingを使ってみた](https://akira-watson.com/wp-content/uploads/2014/07/test-button_00-100x100.jpg)
