アーキテクチャコンポーネントViewModel
が保持されないケースを発見しました-簡単に言えば、次のようになります:
ViewModel
インスタンスが作成されますonCleared
メソッドが呼び出され、新しいオブジェクトが作成されますこの場合、Androidの正常な動作で、私のViewModel
インスタンスが破壊されますか?そうであれば、その状態を維持するための推奨される解決策はありますか?
onCleared
が呼び出されたときにそれを保存することは、私が考えることができる1つの方法ですが、アクティビティが実際に終了するときにも状態を永続化します。もう1つの方法は、onRestoreInstanceState
を使用することですが、(アプリがバックグラウンドにある場合だけでなく)画面が回転するたびに発生します。
そのようなケースを処理するための銀の弾丸はありますか?
はい@tomwyr、これはAndroidフレームワークからのバグでした。 バグの詳細
修正は28.0.0-alpha3およびAndroidX 1.0.0-alpha3で利用可能です
しかし、上記のバージョンに今すぐ更新したくない場合は、次のように解決できます(これは悪い解決策であることはわかっていますが、他の良い方法は見ていません)
アクティビティでonDestroy methodをオーバーライドして、すべての必須フィールドをローカル変数に保存しますsuper.onDestroyを呼び出す前に。次に、super.onDestroyを呼び出してからViewModelを再度初期化し、必要なフィールドをViewModelの新しいインスタンスに割り当てます。
以下のコードはKotlinにあります:
override fun onDestroy() {
val oldViewModel = obtainViewModel()
if (!isFinishing) { //isFinishing will be false in case of orientation change
val requiredFieldValue = oldViewModel.getRequiredFieldValue()
super.onDestroy
val newViewModel = obtainViewModel()
if (newViewModel != oldViewModel) { //View Model has been destroyed
newViewModel.setRequiredFieldValue(requiredFieldValue)
}
} else {
super.onDestroy
}
}
private fun obtainViewModel(): SampleViewModel {
return ViewModelProviders.of(this).get(SampleViewModel::class.Java)
}
申し訳ありませんが、ViewModel
の唯一の目的は、データの所有者がさまざまなライフサイクルイベントを経験する間、データを存続させて保持することです(つまり、「状態を保存する」)。したがって、自分で「状態を保存」する必要はありません。
このことから、「正常な動作ではない」ことがわかります。 onCleared()
は、アクティビティが終了した後にのみ呼び出されます(再度作成されることはありません)。
ViewModel
を使用してViewModelProvider
を作成していますか、それともコンストラクタを使用してインスタンスを作成していますか?
あなたの活動では、次のようなものが必要です:
// in onCreate() - for example - of your activity
model = ViewModelProviders.of(this).get(MyViewModel.class);
// then use it anywhere in the activity like so
model.someAsyncMethod().observe(this, arg -> {
// do sth...
});
これにより、期待どおりの効果が得られます。
サポートライブラリ/ compileSDK/targetSDKを28に変更します。
マルチウィンドウでも同様の問題がありました。分割画面に切り替えると、viewModelが再作成されます。サポートライブラリ28で問題が解決しました。 (私のライフサイクルのバージョンは1.1.1です)