【Android】ViewPager2 + TabLayoutにて複数のフラグメント切替時にViewModelのメソッドが実行できない場合の対応策
AndroidアプリでのViewPager2 + TabLayoutを使ってのFragmentのタブ切り替え実装は、手軽にかつきれいに画面を切り替えられるため使うシーンが多いと思います。
しかし、実装するFragmentの数とタブの遷移の仕方によっては、Fragmentに紐づけて実装するViewModelのメソッド実行や変数の参照などができない(ViewModelが反応しない)ことがありましたので、このケースの対応策を記載します。
問題点
ViewPager2 + TabLayoutの構成でFragment切り替え実装時、以下のケースでViewModelが反応しない。
・タブに紐づけて実装するFragmentが4つ以上
・各Fragmentにはそれぞれ独立したViewModelを以下のコード例1のような形で実装
・タブ切り替え時のイベントとして、OnPageChangeCallbackにて各FragmentのViewModel内のメソッドを実行
・タブを1→3→2番目とタブを一つ飛ばして遷移させた際、最後に選択した2番目のFragmentにてタブ切り替え時の処理が発生しなくなる
val customViewModel: CustomViewModel by viewModels()
原因
上記例では、タブ切り替え動作に伴い2番目のFragmentが一瞬でスルーされてしまうため、「by viewModels()」での初期化実装によりViewModelのインスタンスが作り直されてしまうため
解決策
各FragmentでのViewModelの初期化方法を以下のように変更
lateinit var customViewModel: CustomViewModel
・・・
override fun onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
・・・
customViewModel = ViewModelProvider(this)[CustomViewModel::clas.java]
this.lifecycle.addObserver(customViewModel)
}
(参考)https://stackoverflow.com/a/60885912
解決策としては、ViewModelを初期化する際に、手軽で便利な「by viewModels()」を使っての実装ではなく、少しだけ実装が手間にはなりますがViewModelProviderを使ったlateinitの実装に変更する、となります。
この実装変更で、タブを飛ばしで遷移した後に飛ばしたタブへと戻ってきても、ViewModelのインスタンスが作り直されることなく意図したように実行されます。