LoginSignup
7
9

findViewByIDとDataBinding, DataBindingのおさらい

Last updated at Posted at 2019-03-09

私は、DataBindingを使用する際、xmlファイルのルートを<layout>にした上で、BindするDataクラスを必ず作成する必要があると最近まで思い込んでました。:sweat_smile:
そんなこんなで、DataBindingについて自分用おさらいメモです。

findViewByIDとDataBinding

findViewByIDとDataBindingのViewへの参照の仕組みからおさらいです。

findViewByID

  • ViewHierarchyを上の階層から下の階層へ順に探索します

→ 重いです。(この重い処理が実行時に走ります)

DataBinding

  • ビュー階層上で単一のパスを実行して、IDでビューを抽出します

→ 速いです。(BindingクラスがViewへの参照を保持していてくれているおかげ)

findViewByIDが遅いと言っても、少数のViewに対してでは、DataBindingと差はそんなにないです。あくまで、多数のビューに対してfindViewByIdを呼び出す場合は、DataBindingの方が速い場合があるということです。公式ドキュメント データバインディングライブラリ

DataBindingの流れ

DataBindingの仕組みをおさらいです。

DataBindingのViewへの参照で、
ビュー階層上で単一のパスを実行して、IDでビューを抽出します
と書きましたが、DataBindingのViewへの参照は、具体的には以下の流れです。

  1. コンパイル時にBindingクラスを自動生成
  2. Bindingクラスは、レイアウト内のIDを持つ各ビューに対して、参照を保持
  3. ActivityはBinidngオブジェクトを参照することでViewにアクセス

1. コンパイル時にBindingクラスを自動生成

コンパイル時にBindingクラスを自動生成するには、以下のようにxmlファイルのルートを<layout>にするだけでいいです。その後コンパイルすると、Bindingクラスが自動で生成されます。Bindingクラスはxmlファイル名に応じた名前で生成されてます。
例:activity_main.xml → ActivityMainBinding

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:orientation="vertical">

        <android.support.v7.widget.AppCompatEditText
                android:id="@+id/edit_text"
                android:textSize="15dp"
                android:gravity="center"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
    </LinearLayout>
</layout>

2. Bindingクラスは、レイアウト内のIDを持つ各ビューに対して、参照を保持する

Bindingクラスが生成されました。
生成されたBindingクラスの中身を見ると、bindさせるxmlファイルが指定されていることや、レイアウト内の ID を持つ各ビューに対して、public final フィールドが生成されていることがわかります。

DataBindingでは、ビュー階層上で単一のパスを実行して、IDでビューを抽出します。IDを持つ各ビューに対して参照を保持する、このメカニズムが findViewById を呼び出すよりも速い場合があります。

ActivityMainBinding.kt
public abstract class ActivityMainBinding extends ViewDataBinding {
  @NonNull
  public final AppCompatEditText editText;

  protected ActivityMainBinding(DataBindingComponent _bindingComponent, View _root,
      int _localFieldCount, AppCompatEditText editText) {
    super(_bindingComponent, _root, _localFieldCount);
    this.editText = editText;
  }

  @NonNull
  public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater,
      @Nullable ViewGroup root, boolean attachToRoot) {
    return inflate(inflater, root, attachToRoot, DataBindingUtil.getDefaultComponent());
  }

  @NonNull
  public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater,
      @Nullable ViewGroup root, boolean attachToRoot, @Nullable DataBindingComponent component) {
    return DataBindingUtil.<ActivityMainBinding>inflate(inflater, com.aihana.android.databinding.R.layout.activity_main, root, attachToRoot, component);
  }

  @NonNull
  public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater) {
    return inflate(inflater, DataBindingUtil.getDefaultComponent());
  }

  @NonNull
  public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater,
      @Nullable DataBindingComponent component) {
    return DataBindingUtil.<ActivityMainBinding>inflate(inflater, com.aihana.android.databinding.R.layout.activity_main, null, false, component);
  }

  public static ActivityMainBinding bind(@NonNull View view) {
    return bind(view, DataBindingUtil.getDefaultComponent());
  }

  public static ActivityMainBinding bind(@NonNull View view,
      @Nullable DataBindingComponent component) {
    return (ActivityMainBinding)bind(component, view, com.aihana.android.databinding.R.layout.activity_main);
  }
}

3. ActivityはBinidngオブジェクトを参照することでViewにアクセスできる

Activity側では、 binding = DataBindingUtil.setContentView(this, R.layout.activity_main) でBindingクラスのインスタンスを取得して、binding.editTextのように、xmlで定義したViewにアクセスできました。

MainActivity.kt
class MainActivity : AppCompatActivity(), SampleEventHandler {

    lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        binding.editText.addTextChangedListener(object: CustomTextWatcher{
            override fun afterTextChanged(p0: Editable?) {
                if (binding.editText.text.toString().length < 8) {
                    binding.editText.error = "8文字以内で入力してください"
                } else {
                    binding.editText.error = null
                }
            }
        })
    }
    interface CustomTextWatcher: TextWatcher {
        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
        override fun onTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
    }
}

以上、DataBindingについて超基本ですがおさらいでした。

7
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
9