Android Architecture ComponentsのViewModelを使ってみる
目次
Android Architecture Componentsの背景
Android開発において、近年は、大きな変化が訪れています。
その中でも特に注目したいものが、Android Architecture Components(AAC)です。
AACは、Androidで今まで面倒だったライフサイクルの管理やデータの保持などを扱いやすくするためのライブラリです。
そのAACの中のViewModelについて、今回は紹介したいと思います。
ViewModelの適用手順
それでは、AACのViewModelを実際に使ってみながら、説明していきます。
ViewModelをプロジェクトに導入する
まずは、ViewModelのライブラリを追加していきます
build.gradle (project) にgoogleのリポジトリがなければ、下記のように追加しておきます。
1 2 3 4 5 6 7 8 9 10 11 12 |
[sourcecode lang="swift"] buildscript { ・・・ } allprojects { repositories { google() ・・・ } } [/sourcecode] |
次にbuild.gradle (app) に 下記のようにライブラリを追加します。
1 2 3 4 5 6 7 8 9 10 |
[sourcecode lang="swift"] android { ・・・ } dependencies { ・・・ implementation "android.arch.lifecycle:extensions:1.1.1" ・・・ } [/sourcecode] |
これでViewModelが使用できるようになります。
ViewModelを生成する
ライブラリのViewModelを継承したクラスを作成します。 Activityに反映するデータなどは、すべてViewModelで保持するようにします。
1 2 3 4 5 6 7 |
[sourcecode lang="swift"] import android.arch.lifecycle.ViewModel class MainViewModel : ViewModel() { var name : String = "" } [/sourcecode] |
下記のようにViewModelはViewModelProvidersを経由してインスタンスを取得します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[sourcecode lang="swift"] class MainActivity : AppCompatActivity() { private lateinit var viewmodel: MainViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) viewmodel = ViewModelProviders.of(this).get(MainViewModel::class.java) } } [/sourcecode] |
このViewModelProvidersで、ViewModelが管理されています。 ViewModelProviders.of()の引数に渡されたActivityやFragmentに紐付いたViewModelのインスタンスを返してくれます。 この例だとMainActivityを渡していますが、ここに仮に別のFragmentを渡した場合には、別のインスタンスが返されます。
ViewModelの値を画面に反映する
ViewModelのインスタンスを取得した後は、ViewModelに対して、値をセットしたり、取得を行います。 ViewModelの値でViewに反映するように記述していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[sourcecode lang="swift"] class MainActivity : AppCompatActivity() { private lateinit var viewmodel: MainViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) viewmodel = ViewModelProviders.of(this).get(MainViewModel::class.java) buttonSet.setOnClickListener { viewmodel.name = editName.text.toString() } buttonGet.setOnClickListener { textName.text = viewmodel.name } } } [/sourcecode] |
完成
Activityに直接フィールドを持っていた場合には、画面回転などでActivityが破棄されるとフィールドの値も破棄されてしまいます。 そのためsavedInstanceStateを利用して、値の保存と復元が必要でした。 それに対して、ViewModelは破棄されても再度ViewModelProvidersからインスタンスを取得し直せば、元の値が取得できます。
まとめ
今までは画面回転などでActivityが破棄される場合を考慮して実装していたのが、ViewModelを使うことで、その部分を考慮せずに記述できるようになりました。
ViewModelだけでは、そこまで恩恵がないように見えますが、今回は説明しなかったDatabindingやLiveDataも合わせて使うことで、さらにライフサイクルを意識せずに記述していくことが可能になります。 そのため、DatabindingやLiveDataを使用する上でViewModelの適用は基礎となっていきます。また、ViewとViewModelの責務が明確に分かれていき、FatなActivityやFragmentになりづらくなります。
今回は手作業でプロジェクトにViewModelを導入しました。 しかし、Preview版ですがAndroid Studio 3.2からは、新規にFragmentなどを追加する際に、ViewModel付きを導入した状態で作成できるテンプレートが組み込まれています。
今後、Androidアプリ開発においてMVVMでの設計が多くなっていくのは間違いないのかもしれません。