【Android】LiveData + ViewModelのHello World
概要
Android Jetpack に含まれる「LiveData」についての入門になります。
Jetpackが発表されて約2年ほど立ちますが、この間ほとんどAndroid開発は触っていなかったため、かなり置いていかれてしまいました。
最新のAndroid開発事情に追いつくためにもまずはLiveData,ViewModel周りから触っていきたいと思います。
HelloWoldとして、ボタンを押下したら画面上の数字カウンターをインクリメントしていくよくあるサンプルをViewModel + LiveDataを使って実装します。
環境
- compileSdkVersion: 29
- Kotlin: v1.3.72
- lifecycle-viewmodel-ktx: v2.2.0
- lifecycle-livedata-ktx: v2.2.0
プロジェクトのセットアップ
appディレクトリ配下のbuild.gradleに以下を追加する
dependencies { ・・・ /* ViewModel */ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' /* LiveData */ implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0' ・・・ }
appディレクトリ配下の build.gradle
にViewModelとLiveDataのモジュールインポートを宣言します。
(今までは、lifecycle-extensions
というオールインワンのモジュールがあったようですが、2.2.0でサポートが終わるようなので、今後は個別のモジュールでインポートするのが良さそうです。)
画面のレイアウト
<?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" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="count: 0" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Count up" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView" /> </androidx.constraintlayout.widget.ConstraintLayout>
ここは特別な設定などはありません。
カウントを表示するための TextViewとカウントアップのための Button を用意しています。
ViewModelとLiveDataの準備
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel class CountViewModel : ViewModel() { // NOTE: TextViewに表示するテキスト用のLiveData. // 変更可のためMutableLiveDataで作成する var text = MutableLiveData<String>() // NOTE: カウント管理用の変数 private var count = 0 // カウントアップボタンを押下されたときのイベントを受け取るためのメソッド fun countUp() { count += 1 text.value = "count $count" } }
ViewModelクラスを継承したカウントアップの値を保持する独自のViewModelを作成します。
TextViewに設定するためのtextを LiveData
として用意します。
今回は、変更可能なデータとして扱いたいため MutableLiveData
を使用しています。
ViewModelのセットアップ
import android.os.Bundle import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // NOTE: ViewModelの生成 val viewModel = ViewModelProvider(this).get(CountViewModel::class.java) // NOTE: LiveDataの値の変更を監視。変更を受け取ったらTextViewに値をセット。 viewModel.text.observe(this, Observer { resource -> findViewById<TextView>(R.id.textView).text = resource } ) // NOTE: ボタンのクリックリスナーの設定 findViewById<TextView>(R.id.button).setOnClickListener{ viewModel.countUp() } } }
最後にActivityでViewModelを生成します。
ViewModelのインスタンスは、ViewModelPlovider
を使って作成します。
ViewModelPloviderには、Activityを引数として渡す必要があります。
生成されたViewModelインスタンスのtext LiveDataに対して、observe
メソッドを使うことで値の変更を監視することができます。
ここに渡した Observer
のクロージャに変更した値が送られるため、その値とTextViewを紐付けることでリアクティブなデータ更新ができるようになります。
まとめ
基本的な使い方としてはシンプルでコードもスッキリしそうです。
LiveData+ViewModelは、基本的にはDataBindingと組み合わせて使うことが多そうなので、そのへんも次回は基本から調べて行こうと思います。