日々是好日

プログラミングについてのあれこれ、ムダ知識など

MVVM 完全に理解した - 2

今回は ViewModel について。

ViewModel とは

developer.android.com

The ViewModel class allows data to survive configuration changes such as screen rotations.

Activity が破棄・再生成される画面回転などの操作について、(UI と関連した)データをロストさせないようにできるクラスとのこと。

ViewModel クラスのメソッド

public abstract class ViewModel {
    protected void onCleared() { }
}

onCleared のみが定義されています。
詳しくは後述。

実装例

リファレンスの実装例を見てみます。

class MyViewModel : ViewModel() {
    // LiveData を保持
    private lateinit var users: MutableLiveData<List<User>>

    //LiveData を取得
    fun getUsers(): LiveData<List<User>> { ... }
    ...
}

Activity からアクセスするときは次の通り。

class MyActivity : AppCompatActivity() {
    override fun onCreate( ... ) {
        //MyViewModel の生成
        val model = ViewModelProviders.of(this).get(MyViewModel::class.java)

        //LiveData#observe
        model.getUsers().observe(this, Observer<List<User>> { users ->
            // UI のアップデート処理を記述
            // users is List<User>
        })
    }
}

Create a ViewModel the first time the system calls an activity's onCreate() method

Activity#onCreate メソッドが呼ばれるときに ViewModel を生成しなさいよ~とのこと。
ここで、

ViewModel は view や Lifecycle, または Activity context への参照を保持しているクラスを "絶対に" 参照するなよ!!

との注意書きが…!

ViewModel オブジェクトは、View や LifecycleOwners ( Activity や Fragment ) などのインスタンスよりも長生きするように設計されている

すなわち、ViewModel 内でこれら寿命が短いインスタンスを参照すると、メモリリークする可能性が出てきます。参照だめ絶対。
一方で、この構造は View や Lifecycle オブジェクトを知らないくても容易にテストが可能であることを示します。

もし、システムサービスなどのために Application context が必要な場合は、AndroidViewModel を拡張して使うことができます。
AndroidViewModel はコンストラクタで Application を受け取るためです。

(これ Toast や Snackbar の操作に使えそう)

AndoridViewModel (Application application)

さて、さっきちらっと出てきた onCleared ですが、これどこで呼ばれるのかというとActivity#onDestroy 後のほんとに最後だそうです。

https://developer.android.com/images/topic/libraries/architecture/viewmodel-lifecycle.png

画面回転で onDestroy 呼ばれても死にません。 Activity#finish() が呼ばれた後にコールされるようです。

まとめ

公式リファレンスでも、ViewModel は LiveData と一緒に使うのが前提みたいになってますね。
次は DataBinding について。