AndroidViewModel с SavedState - PullRequest
       4

AndroidViewModel с SavedState

1 голос
/ 06 апреля 2020

Мне нужно использовать AndroidViewModel с контекстом приложения и SavedStateHandle. Я уже работал с контекстом приложения, но мне не удается добавить к нему SavedStateHandle.

Это то, что у меня есть, только с контекстом приложения:

// A1. get ViewModel in Fragment
val viewModel = ViewModelProvider(viewLifecycleOwner).get(MyViewModel::class.java)

// A2. MyViewModel derives from my custom BaseAndroidViewModel
class MyViewModel(application: Application) :BaseAndroidViewModel(application)

// A3. BaseAndroidViewModel in turn derives from AndroidViewModel
open class BaseAndroidViewModel(application: Application) : AndroidViewModel(application)

Я предполагаю для этот вопрос, вероятно, может быть уменьшен до:

// B1. get ViewModel in Fragment
val viewModel = ViewModelProvider(viewLifecycleOwner).get(MyViewModel::class.java)

// B2. BaseAndroidViewModel in turn derives from AndroidViewModel
class MyViewModel(application: Application) : AndroidViewModel(application) 

Итак, для того, чтобы иметь также SavedStateHandle в MyViewModel, как бы мне пришлось изменить вызов во фрагменте (строка B1 в пример кода)? Нужен ли явный вызов на завод SavedStateViewModelFactory? Как именно это будет выглядеть? (Я все еще новичок в Kotlin / Android, я никогда раньше не работал с фабрикой)

1 Ответ

1 голос
/ 06 апреля 2020

РЕДАКТИРОВАТЬ: в окончательном выпуске AndroidX-Activity 1.2.0 и AndroidX-Fragment 1.1.0, они сделали SavedStateViewModelFactory фабрикой по умолчанию в AppCompatActivity / Fragment, поэтому нет необходимости переопределять фабрику по умолчанию (которая является что делает вторая половина этого ответа.)

Обновление и затем использование

class MyViewModel(val savedStateHandle: SavedStateHandle): ViewModel()

class MyAndroidViewModel(application: Application, val savedStateHandle: SavedStateHandle): AndroidViewModel(application)

Должно просто сработать.


ОРИГИНАЛ:

как мне изменить вызов во фрагменте (строка B1 в примере кода)? Нужен ли явный вызов фабрике SavedStateViewModelFactory? Как именно это будет выглядеть?

В AndroidX-Activity 1.2.0 они добавили новый метод под названием getDefaultViewModelProviderFactory():

+    @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());
+    }
+

, который означает, что если у меня есть BaseActivity или BaseFragment, я могу поменять его на SavedStateViewModelFactory с viewmodel-savedstate:

class BaseActivity: AppCompatActivity() {
    override fun getDefaultViewModelProviderFactory(): ViewModelProvider.Factory = 
        SavedStateViewModelFactory(application, this, intent?.extras ?: Bundle())
}

class BaseFragment: Fragment() {
    override fun getDefaultViewModelProviderFactory(): ViewModelProvider.Factory = 
        SavedStateViewModelFactory(requireActivity().application, this, arguments ?: Bundle())
}

Как только у вас есть это, вы можете положиться на автомат c создание экземпляра ViewModel с SavedStateHandle в качестве одного из аргументов:

class MyViewModel(val savedStateHandle: SavedStateHandle): ViewModel()

class MyAndroidViewModel(application: Application, val savedStateHandle: SavedStateHandle): AndroidViewModel(application)

Остерегайтесь того, что порядок application, savedStateHandle ожидается SavedStateViewModelFactory.

Однако, если вам нужно пользовательские аргументы в довершение всего, тогда вам нужно будет указать object: AbstractSavedStateViewModelFactory при вызове метода ViewModelProvider(viewModelStoreOwner).get(...)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...