こんにちは。
アプリケーション共同開発部 名古屋開発課の早川です。
Google I/O 2015 で発表された、Android Data Binding ですが、
2016 年中にもアップデートが行われ、使いやすいものになってきております。
本記事では、改めて Android DataBinding の使い方と、個人的な気になる点など紹介させていただきます。
はじめに
本記事は以下の開発環境で確認した内容となります。
Android Studio 2.2.2
環境構築
Google より サポートライブラリとして用意されている、バインディングライブラリを利用します。
以下開発環境制限です。
サポート OS バージョン | Android OS 2.1 以降 |
開発環境 | Android Studio 1.3 以降 Android Plugin for Gradle 1.5.0-alpha1 以降 |
Android Studio より作成した Android プロジェクトの build.gradle に以下の設定を追加します。
build.gradle
android { .... dataBinding { enabled = true } }
実装
今回はデータバイディングを行うミニマムケースとして、レイアウトの用意・データの用意・バインディング処理 の3ステップで実装していきます。
レイアウトの用意
データバインディングで利用するレイアウトファイルは、通常の Android アプリで使用されるレイアウトファイルとは少し異なります。
以下レイアウトファイル例です。
main_activity.xml
<?xml version="1.0" encoding="utf-8"?> <!-- ルート要素 --> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <!-- データ要素 --> <data> <variable name="user" type="com.testapp.User"/> </data> <!-- レイアウト要素 --> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.name}"/> <!-- データ設定箇所 --> </LinearLayout> </layout>
ルート要素として <layout> 、データ要素として <data> を使用します。
データ要素の variable 要素でデータバインディング時に使用されるプロパティを設定します。
レイアウト要素ではこれまで通りのレイアウトフォーマットで記述しますが、データ要素より設定したい箇所は@{}で記述します。
データの用意
レイアウトファイルで記述した data 要素のクラスオブジェクトを用意します。
以下クラス例です。
User.java
public class User { public final String name; public User(String name) { this.name = name; } }
バインディング処理
今回のケースは Activityクラス (MainActivity.java) で上記のレイアウトファイルを使用するケースとします。
この場合 Activity には以下の処理が必要となります。
MainActivity.java
public class MainActivity extends AppCompatActivity { ・・・ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity); User user = new User("user_name"); binding.setUser(user); } ・・・ }
Tips!!
- 自動生成される MainActivityBinding (バインディングクラス)はレイアウトファイルの名前をパスカルケースに変換して “Binding” をつけた名前になります。
main_activity.xml -> MainActivityBinding - binding.setUser(〜) は data 要素の name 属性を元に setter メソッドとして生成されます。
- binding.setUser(〜) を行うことで対象レイアウトが表示される前に User クラスの name プロパティが表示される動きとなります。
非常にシンプルなケースではありますが、データバインディングを利用した実装パターンになります。
データ属性を増やしたり、レイアウトファイルの中で処理を記述したりと、まだまだ色々な処理を行うことができますので、気になった方は公式ページも読んでみてください。
気になった点
Android DataBinding を使って気になった感じたことや気になった点を挙げておきます。
findViewById を少なくできる
Android 開発をしていると、findViewById の処理がどうしてもつきまといます。
データバインディングを利用した場合、レイアウトファイルの中に定義した View 要素に android:id を設定することでバインディングクラスよりプロパティ参照することができます。
これによって、findViewById()によって View 要素を取得する処理を記述する必要がなくなるのはとても便利ですね。
main_activity.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"> <TextView android:id="@+id/name_text" <!-- idをつける --> android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.name}"/> </LinearLayout> </layout>
MainActivity.java
public class MainActivity extends AppCompatActivity { ・・・ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity); ・・・ binding.nameText.setEnable(true); // バインディングクラスから直接参照可能にります } ・・・ }
Activity / Fragment の肥大化を防げる
Activity や Fragment に コンポーネントのリスナー処理などを書いてしまいがちですが onClick といったイベント処理のリスナーはレイアウトファイルに記述することで自動生成がされるので、必然的にコード量を減らせます。
元々、レイアウトファイルから指定することは可能でしたが、データ要素のクラスを指定できるため、呼び出し先を明確に指定することが可能になりました。
main_activity.xml
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="presenter" type="com.testapp.Presenter"/> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{presenter.onButtonClick}"/> <!-- onClick処理を記載 --> </LinearLayout> </layout>
Presenter.java
public class Presenter { public void onButtonClick(View view){ // Button 押下処理がよばれる } }
レイアウトファイルのタイプミスが判定しにくい
レイアウトファイルからメソッド参照を記述する際、メソッド名の補完が現在は行われないため、タイプミスの判定が難しいです。
コンパイルエラー発生時には、Binding クラスが生成されずに、多くエラーが表示されます。
コンパイルエラー発生時には、エラー内容の一番下に要因が書かれていることが多いので、そこをチェックして、落ち着いて対処しましょう。
今後リリースされる Android Studio 2.3 には XML エディターからのサポートが追加されるようです!
Android Studio Project Site
Activity / Fragment に依存した処理の連携が複雑になる
データバインディングを利用することで、Activity / Fragment クラスから別のクラスに処理を記載できますが、どうしても Activity / Fragment に依存した処理を記述するケースがあるので、連携処理が複雑になりがちです。
データ要素のクラスに Activity / Fragment インスタンスを渡すことは循環参照につかながり兼ねないため、リスナー処理を用意するなどして、うまく処理を通知してあげる構成を用意する必要があります。
このあたりベストプラクティスが何かを今後も追求していく必要があります。
まとめ
今回はデータバインディング導入方法や使用した際に気になった部分をまとめさせていただきました。
使用方法については公式のドキュメントが用意されており、取り組みやすい技術ではありますが、これまでとはレイアウトファイルの書き方から異なるため、その点の違和感をどう学習してなくしていくかかがキモでしょうか。
今後の Android Studio の更新でもっと使いやすい技術になっていくと思われますので、まだ取り組まれていない方は取り組んでみてください。
フェンリルのオフィシャル Twitter アカウントでは、フェンリルプロダクトの最新情報などをつぶやいています。よろしければフォローしてください!