Итак, я проверил документы и, как я правильно понял, теперь я должен использовать
ViewModelProvider.AndroidViewModelFactory.getInstance(
this.getApplication()).create(CanteensViewModel.class);
Пожалуйста, поделитесь ссылкой на эти "документы", которые вы упомянули, потому что это НЕ первое когда я вижу этот код, и все же он был в равной степени неправильным в обоих случаях.
Код, который вы на самом деле должны использовать:
new ViewModelProvider(this).get(CanteensViewModel.class);
Есть ли способ получить доступ к ViewModel активности из фрагментов? Или было бы лучше воссоздать ViewModel в каждом фрагменте путем
new ViewModelProvider(requireActivity()).get(CanteensViewModel.class);
Рассмотрим также получение SavedStateHandle
в качестве аргумента в вашем AndroidViewModel
, а не только Application
.
Если вы спросите меня, очевидно, удаление ViewModelProviders.of()
было ошибкой API, но это то, что мы имеем сейчас.
РЕДАКТИРОВАТЬ: С помощью предоставленной трассировки стека, я наконец-то могу немного понять, что происходит.
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:219)
Мы используем NewInstanceFactory
по умолчанию. Что делает по умолчанию NewInstanceFactory
? Он просто вызывает конструктор без аргументов , если доступен.
Подождите, что? Разве это не должно заполнять Application
для AndroidViewModel
?
Теоретически да, если вы получили исходное значение по умолчанию ViewModelProvider.Factory
, но это не то!
Почему это не тот, который может заполнить AndroidViewModel?
См. этот коммит
Add default ViewModel Factory interface
Use a marker interface to allow instances of
ViewModelStoreOwner, such as ComponentActivity
and Fragment, to provide a default
ViewModelProvider.Factory that can be used with
a new, concise ViewModelProvider constructor.
This updates ComponentActivity and Fragment to
use that new API to provide an
AndroidViewModelFactory by default. It updates
the 'by viewModels' Kotlin extensions to use
this default Factory if one isn't explicitly
provided.
Также
ComponentActivity:
+ @NonNull
+ @Override
+ public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
+ if (getApplication() == null) {
+ throw new IllegalStateException("Your activity is not yet attached to the "
+ + "Application instance. You can't request ViewModel before onCreate call.");
+ }
+ return ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication());
+ }
+
И самое главное
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
Это означает, что вы получаете фабрику поставщика модели представления по умолчанию, которая может правильно настроить AndroidViewModel if ViewModelStoreOwner реализует HasDefaultViewModelProviderFactory
.
Теоретически, ComponentActivity
действительно HasDefaultViewModelProviderFactory
; и AppCompatActivity
простирается от ComponentActivity
.
В вашем случае, однако, это не так. По какой-то причине ваш AppCompatActivity
не является HasDefaultViewModelProviderFactory
.
Я думаю, что решение вашей проблемы - обновить Lifecycle до 2.2.0, а ТАКЖЕ обновить implementation 'androidx.core:core-ktx
до как минимум 1.2.0. (в частности, как минимум AndroidX-Activity 1.1.0 и AndroidX-Fragment 1.2.0).