SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

一歩進んだAndroidアプリ開発ができる「Android Jetpack」入門

画面へのデータ反映処理を自動化できるデータバインディング! コードのバリエーションを紹介

一歩進んだAndroidアプリ開発ができる「Android Jetpack」入門 第7回


  • X ポスト
  • このエントリーをはてなブックマークに追加

リスナ登録

 エンティティを利用することで、画面へのデータ反映がまとめて行えるようになりました。ただ、いまだに問題として残っているのがリスナ登録です。ビューバインディングやデータバインディングを利用することで、ボタンなどの画面部品へのアクセスが容易になったとはいえ、クリックリスナ登録コードはこれまで通りsetOnClickListener()メソッドを利用しています。データバインディングでは、このクリックリスナ登録も効率よくできます。最後にその方法を紹介しておきます。

イベント処理を記述したクラス

 データバインディングを利用してリスナを登録する場合は、イベント処理、すなわち、これまでリスナクラス内のメソッドに記述していた処理を、ひとつのメソッドとして別クラスに記述します。例えば、前節のサンプルのボタンがタップされた時の処理をonBtnGenerateClick()メソッドとして実装するならば、このメソッドが定義されたクラスは、Javaではリスト6、Kotlinではリスト7のようになります。

リスト6:イベント処理が記述されたクラス(Java版)
public class MainHandlers {
  MainViewModel _mainViewModel;  // (1)
  ActivityMainBinding _activityMainBinding;  // (2)
  public MainHandlers(MainViewModel mainViewModel, ActivityMainBinding activityMainBinding) {  // (3)
    _mainViewModel = mainViewModel;
    _activityMainBinding = activityMainBinding;
  }
  public void onBtnGenerateClick(View view) {  // (4)
    _mainViewModel.generateNewRectangle();  // (5)
    _activityMainBinding.setRectangle(_mainViewModel.getRectangle());  // (6)
  }
}
リスト7:イベント処理が記述されたクラス(Kotlin版)
class MainHandlers(private val _mainViewModel: MainViewModel, private val _activityMainBinding: ActivityMainBinding) {  // (1)〜(3)
  fun onBtnGenerateClick(view: View) {  // (4)
    _mainViewModel.generateNewRectangle()  // (5)
    _activityMainBinding.rectangle = _mainViewModel.rectangle  // (6)
  }
}

 リスト6、リスト7ともに、イベント処理を記述したクラスをMainHandlersとしています。そして、これまでButtonClickListenerクラスのonClick()メソッド内に記述していた処理をそのまま記述したメソッドとして、onBtnGenerateClick()を定義しています。それが、(4)です。その際、onClick()メソッドのシグネチャと同じく、引数としてViewを定義しています。

 メソッド内の処理は、(5)でViewModel内に用意した新たなRectangleオブジェクトを生成するメソッドを実行し、そのようにして新たに生成されたRectangleオブジェクトを(6)でバインディングオブジェクトにセットしています。

 ただし、このようにViewModelオブジェクトとバインディングオブジェクトをイベント処理メソッド内部で利用するため、(1)と(2)のように、MainHandlersクラスのフィールドとしてこれらのオブジェクトを用意し、(3)のコンストラクタでオブジェクトそのものをアクティビティからもらうようにしておきます(Kotlinではこれがクラス宣言の1行にまとめられています)。

レイアウトxmlでのイベント処理クラスの利用

 前項で作成したMainHandlersクラスをレイアウトxmlで利用する場合は、リスト8のコードとなります。

リスト8:イベント処理クラスの設定コード
<?xml version="1.0" encoding="utf-8"?>
<layout
  xmlns:android="http://schemas.android.com/apk/res/android"
  …>
  <data>
    :
    <variable
       name="mainHandlers"
       type="com.….MainHandlers" />  (1)
  </data>
  <androidx.constraintlayout.widget.ConstraintLayout
    …>
     :
    <Button
      android:id="@+id/btnGenerate"
      :
      android:onClick="@{mainHandlers::onBtnGenerateClick}"/>  (2)
     :
</layout>

 エンティティなどと同様に、イベント処理クラスも、リスト8の(1)のようにvariableタグに変数として定義できます。そして、その変数mainHandlers内のメソッドをclickイベントと結びつけるコードが(2)です。

 クリックイベントを設定する属性であるonClickに「@{変数名::メソッド名}」を記述するだけです。あとは、アクティビティでイベント処理クラス(MainHandlers)をnewして、バインディングオブジェクトにセットするだけでリスナ設定が完了します。

イベント処理メソッドのシグネチャ

 ただし、この方法によるリスナ設定には、ひとつ制約があります。それは、イベント処理メソッドのシグネチャを本来のリスナクラスのメソッドと全く同じにする必要があることです。そのため、リスト6やリスト7のonBtnGenerateClick()の引数として、View型のviewを定義しています。

 一方で、onBtnGenerateClick()内では、このviewは利用されていません。本来のリスナクラス内のメソッドのように、インターフェースで定義されたものならば使っていなくても引数は定義しておく必要があります。しかし、onBtnGenerateClick()のように独自に定義できるメソッドで不要な引数を定義するのは、できれば避けたいです。

 データバインディングでは、実は、この引数は、必ずしも本来のリスナクラスのメソッドシグネチャに一致させなくてもよく、以下のシグネチャでもかまいません。

public void onBtnGenerateClick() {
  :
}

 ただし、その場合は、レイアウトxmlファイル内での@{ }の記述が次のように変わります。

android:onClick="@{(view) -> mainHandlers.onBtnGenerateClick()}"

 @{変数名::メソッド名}の代わりにラムダ式を記述します。その構文は以下の通りです。

[構文]イベント処理メソッドの登録

@{(本来の引数) -> イベント処理オブジェクト変数.イベント処理メソッド(引数, …)}

 ラムダ式の引数には、本来のリスナクラスのメソッドシグネチャに合わせた引数を記述します。->の右側にはイベント処理オブジェクトを定義した変数に.(ドット)アクセスでイベント処理メソッドの呼び出しコードを記述します。その際、もし引数が必要ならば渡すことも可能です。例えば、onBtnGenerateClick()メソッドシグネチャが、リスト6やリスト7と同じくviewが引数として定義されているならば、以下のようなコードになります。

android:onClick="@{(view) -> mainHandlers.onBtnGenerateClick(view)}"

 このように、ラムダ式を使ったイベント処理メソッドでのリスナ設定の方が、より柔軟なコードが記述できます。

まとめ

 Android Jetpackについて紹介していく本連載の第7回は、いかがでしたでしょうか。

 今回は、前回の続きとして、データバインディングを掘り下げ、式言語、エンティティの利用、リスナ登録を紹介しました。次回は、さらにデータバインディングを掘り下げ、監視オブジェクトの利用や双方向データバインディングを紹介していきます。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
一歩進んだAndroidアプリ開発ができる「Android Jetpack」入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 齊藤 新三(サイトウ シンゾウ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook <個人紹介>WINGSプロジェクト所属のテクニカルライター。Web系製作会社のシステム部門、SI会社を経てフリーランスとして独立。屋号はSarva(サルヴァ)。HAL大阪の非常勤講師を兼務。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/18644 2023/11/30 16:35

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング