In meinem Fall war der Grund, dass ich zu früh versucht habe, eine gemeinsam genutzte Instanz des ViewModel in meinem Fragment abzurufen - bevor die Aktivität erstellt wurde. Was passiert, wenn die Anwendung nach dem Beenden ihren Status wiederherstellt?
Voraussetzungen :
- Mein ViewModel hat einen öffentlichen Konstruktor.
- Mein ViewModel hat mehrere Argumente. Dies ist jedoch absolut in Ordnung, da ich ViewModelFactory zum Erstellen des ViewModel verwende.
- Mein Fragment und meine Aktivität verwenden dieselbe Instanz des ViewModel . Mit anderen Worten: Aktivität erstellt das ViewModel und das Fragment erhält später dieselbe Instanz.
Code in Aktivität:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//factory is constructed using Dagger
val factory = App.get().components().appComponent.getMapViewModelFactory()
//activity creates the instance of MapViewModel
viewModel = ViewModelProviders.of(this, factory)[MapViewModel::class.java]
}
Code in Fragment:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//fragment receives the instance of MapViewModel
viewModel = ViewModelProviders.of(activity!!)[MapViewModel::class.java]
...
}
Wenn ich die App zum ersten Mal öffne, funktioniert alles einwandfrei: Aktivität erstellt eine Instanz von ViewModel; Ich öffne Fragment, das die Instanz von ViewModel erhält. Wenn die Anwendung jedoch versucht, ihren Status nach dem Beenden wiederherzustellen, ruft sie zuerst den Hauptteil von onCreate des Fragments und dann den Hauptteil von onCreate der Aktivität auf. Zu diesem Zeitpunkt kann das Fragment das ViewModel nicht abrufen, da Activity es noch nicht erstellt hat.
Lösung 1 : Verschieben Sie den Code, wenn das Fragment das ViewModel von onCreate nach onViewCreated erhält. Dies ist in Ordnung, da ich alle Live-Daten auch in onViewCreated beobachte.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = activity?.run { ViewModelProviders.of(this)[MapViewModel::class.java] } ?: throw Exception("Invalid Activity")
viewModel.getSurveyDateLiveData().observe(viewLifecycleOwner, Observer<String> { dateTextView.text = it })
...
}
Lösung 2 : Erstellen Sie die Instanz von ViewModel in Activity.onCreate, bevor super.onCreate aufgerufen wird. In diesem Fall können Sie das ViewModel in onCreate Ihres Fragments abrufen .
override fun onCreate(savedInstanceState: Bundle?) {
val factory = App.get().components().appComponent.getMapViewModelFactory()
viewModel = ViewModelProviders.of(this, factory)[MapViewModel::class.java]
super.onCreate(savedInstanceState)
Timber.d("cc: onCreate: $this ")
}
Lösung 3 :
Wenn Sie eine Repository-Instanz in Ihr ViewModel einfügen, überprüfen Sie, ob Sie @Inject constructor(...): ViewModel()
Ihr Repository nicht zum Einfügen verwenden, sondern**@ViewModelInject constructor(...): ViewModel()**