带有 SavedState 的 AndroidViewModel
AndroidViewModel with SavedState
我需要使用带有应用程序上下文的 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)
因此,对于在 MyViewModel
中也有一个 SavedStateHandle
,我将如何修改片段中的调用(示例代码中的第 B1
行)?我需要显式调用工厂 SavedStateViewModelFactory
吗?那到底会是什么样子? (我对Kotlin/Android还是个新手,我以前从未在工厂工作过)
编辑: 在 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)
应该就可以了。
原版:
how would I have to modify the call in the fragment (line B1 in the example code) ? Do I need an explicit call to the factory SavedStateViewModelFactory? How exactly would that look like?
在 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
,我可以将其换成 viewmodel-savedstate
中的 SavedStateViewModelFactory
:
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())
}
一旦你有了它,你就可以依赖 ViewModel 的自动实例化,并将 SavedStateHandle
作为他们的参数之一:
class MyViewModel(val savedStateHandle: SavedStateHandle): ViewModel()
class MyAndroidViewModel(application: Application, val savedStateHandle: SavedStateHandle): AndroidViewModel(application)
请注意 application, savedStateHandle
的顺序是 SavedStateViewModelFactory
所期望的。
但是,如果您确实需要自定义参数,那么您必须在调用 ViewModelProvider(viewModelStoreOwner).get(...)
方法时提供 object: AbstractSavedStateViewModelFactory
我需要使用带有应用程序上下文的 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)
因此,对于在 MyViewModel
中也有一个 SavedStateHandle
,我将如何修改片段中的调用(示例代码中的第 B1
行)?我需要显式调用工厂 SavedStateViewModelFactory
吗?那到底会是什么样子? (我对Kotlin/Android还是个新手,我以前从未在工厂工作过)
编辑: 在 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)
应该就可以了。
原版:
how would I have to modify the call in the fragment (line B1 in the example code) ? Do I need an explicit call to the factory SavedStateViewModelFactory? How exactly would that look like?
在 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
,我可以将其换成 viewmodel-savedstate
中的 SavedStateViewModelFactory
:
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())
}
一旦你有了它,你就可以依赖 ViewModel 的自动实例化,并将 SavedStateHandle
作为他们的参数之一:
class MyViewModel(val savedStateHandle: SavedStateHandle): ViewModel()
class MyAndroidViewModel(application: Application, val savedStateHandle: SavedStateHandle): AndroidViewModel(application)
请注意 application, savedStateHandle
的顺序是 SavedStateViewModelFactory
所期望的。
但是,如果您确实需要自定义参数,那么您必须在调用 ViewModelProvider(viewModelStoreOwner).get(...)
方法时提供 object: AbstractSavedStateViewModelFactory