SHOEISHA iD

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

CodeZine(コードジン) DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

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

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

データ更新に応じてUI変更を自動実行しよう ―データを非同期でUIに反映できる「LiveData」とは?

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

UI更新処理はオブザーバを利用

 前節でViewModelにLiveDataオブジェクトが用意できました。次に、このLiveDataオブジェクトに、UIの更新処理を登録していきます。

オブザーバの登録はobserve()メソッド

 図3にもあるように、LiveDataがデータの変更を検知してUIの変更処理を自動実行するためには、そのLiveDataにUIの変更処理が登録されている必要があります。このUIの変更処理のことをオブザーバといいます。そして、オブザーバの登録は、アクティビティやフラグメントの役割となります。これは、Javaではリスト3のようなコードとなります。

リスト3:MainActivityでのオブザーバ登録処理(Java版)
public class MainActivity extends AppCompatActivity {
  :
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    :
    LiveData<Cocktailmemo> cocktailmemoLiveData = _mainViewModel.getCocktailmemoLiveData();  // (1)
    cocktailmemoLiveData.observe(MainActivity.this, new CocktailmemoObserver());  // (2)
      :
  }
  :
}

 リスト3にあるように、オブザーバの登録処理は、原則onCreate()メソッド内で行います。その際、まず、(1)のようにViewModelから内部に保持しているLiveDataオブジェクトを取得します。そして、(2)のように、そのLiveDataオブジェクトのobserve()メソッドを実行してオブザーバの登録を行います。

 このobserve()メソッドの引数は2個であり、第1引数は、LifecycleOwnerを渡します。LifecycleOwnerは、Androidのライフサイクルを担うオブジェクトを表します。もしこのオブザーバ登録がアクティビティの場合は、(2)のように、自分自身のオブジェクトを渡せば問題ありません。一方、フラグメントの場合は、getViewLifecycleOwner()メソッドの戻り値を渡します。

 第2引数は、まさにオブザーバオブジェクトであり、このクラスは自作します。作り方は次項で紹介します。(2)ではそのように自作したCocktailmemoObserverクラスをnewして渡しています。

 Kotlinコードも同様であり、リスト4のようになります。

リスト4:MainActivityでのオブザーバ登録処理(Kotlin版)
class MainActivity : AppCompatActivity() {
  :
  override fun onCreate(savedInstanceState: Bundle?) {
    :
    _mainViewModel.cocktailmemoLiveData.observe(this@MainActivity, CocktailmemoObserver())
    :
  }
  :
}

 リスト3のJavaコードをそのままKotlinコードに置き換えた内容になっています。なお、このコードの記述がフラグメントの場合は、observe()メソッドの第1引数は、JavaのようにgetViewLifecycleOwner()メソッドの戻り値ではなく、viewLifecycleOwnerプロパティとなります。

オブザーバクラスの作り方

 では、そのobserver()メソッドの第2引数として渡すオブザーバクラスの作り方を見ていきましょう。リスト3で渡しているJava版CocktailmemoObserverクラスは、MainActivityのメンバクラスとして作成し、リスト5のコードとなります。

リスト5:CocktailmemoObserverクラス(Java版)
public class MainActivity extends AppCompatActivity {
  :
  private class CocktailmemoObserver implements Observer<Cocktailmemo> {  // (1)
    // データ変更に応じてUIを変更する処理メソッド。
    @Override
    public void onChanged(@Nonnull Cocktailmemo cocktailmemo) {  // (2)
      // カクテル名を表示欄に反映。
      TextView tvCocktailName = findViewById(R.id.tvCocktailName);  // (3)
      tvCocktailName.setText(cocktailmemo.name);  // (3)
      // 感想を入力欄に反映。
      EditText etNote = findViewById(R.id.etNote);  // (4)
      etNote.setText(cocktailmemo.note);  // (4)
      // ボタンと入力欄の有効・無効を切り替え。
      Button btnSave = findViewById(R.id.btnSave);  // (5)
      if(cocktailmemo.id == -1) {  // (6)
        etNote.setEnabled(false);
        btnSave.setEnabled(false);
      }
      else {
        etNote.setEnabled(true);
        btnSave.setEnabled(true);
      }
    }
  }
}

 オブザーバクラスの作り方は以下の通りです。

1. Observerインターフェースを実装する。

 リスト5の(1)が該当します。その際、ジェネリクスとして、このクラスをオブザーバとして登録するLiveDataの内部で保持しているデータと同じ型を指定します。前節で紹介したように、cocktailmemoLiveDataの内部に保持しているデータは、Cocktailmemoエンティティです。これに合わせて、(1)でもCocktailmemoをジェネリクスとして型指定しています。

2. onChanged()メソッドをオーバーライドし、その中にUIの変更処理を記述する。

 リスト5の(2)が該当します。このonChanged()メソッドの引数は、(1)のObserverインターフェースのジェネリクスとして型指定したデータ型となります。また、nullになることはないため、@Nonnullアノテーションを付与しています。そして、LiveData内に保持しているデータが変更された場合、新しいデータが格納されたものがこの引数として渡されます。そのため、メソッド内には、この引数のデータを利用して、UIの変更処理を記述します。

 リスト5に記述したUIの変更処理は、(3)がカクテル名を表示しているTextViewの表示文字列の変更処理、(4)が感想の入力欄であるEditText内の文字列の変更処理、(5)

 と(6)以降が感想入力欄と[保存]ボタンの利用可、不可の切り替え処理となっています。

 (6)以降について少し補足しておくと、引数として渡ってくるCocktailmemoオブジェクトは、リストからカクテルが選択されていない場合は、そのidが-1となるように次節でコーディングします。それを受けて、idが-1の場合は、データが入力できず、保存ができない状態と判断して、入力欄とボタンを利用不可にしています。一方、-1ではない場合に、利用できるようにしています。

 このように、データに応じたUIの変更処理をオブザーバにまとめることにより、アクティビティやフラグメント内に散在していたUIの変更処理を、まとめることができます。

 このオブザーバクラスの作り方はKotlinでも同じであり、リスト6のコードとなります。リスト5を、単にKotlinコードに置き換えたコードとなっています。リスト5に対応する形で番号を記載していますので、参考にしてください。

リスト6:CocktailmemoObserverクラス(Kotlin版)
class MainActivity : AppCompatActivity() {
  :
  private inner class CocktailmemoObserver : Observer<Cocktailmemo> {  // (1)
    // データ変更に応じてUIを変更する処理メソッド。
    override fun onChanged(cocktailmemo: Cocktailmemo) {  // (2)
      // カクテル名を表示欄に反映。
      val tvCocktailName = findViewById<TextView>(R.id.tvCocktailName)  // (3)
      tvCocktailName.text = cocktailmemo.name  // (3)
      // 感想を入力欄に反映。
      val etNote = findViewById<EditText>(R.id.etNote)  // (4)
      etNote.setText(cocktailmemo.note)  // (4)
      // ボタンと入力欄の有効・無効を切り替え。
      val btnSave = findViewById<Button>(R.id.btnSave)  // (5)
      if(cocktailmemo.id == -1) {  // (6)
        etNote.isEnabled = false
        btnSave.isEnabled = false
      }
      else {
        etNote.isEnabled = true
        btnSave.isEnabled = true
      }
    }
  }
}

次のページ
MutableLiveDataのデータ更新

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

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

もっと読む

この記事の著者

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

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 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本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

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

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

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/18090 2023/08/08 11:00

おすすめ

イベント

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

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

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

メールバックナンバー