带有 SavedState 的 AndroidViewModel

ste*_*wpf 7 android factory android-viewmodel android-architecture-components

我需要使用一个AndroidViewModelwith 应用程序上下文和一个SavedStateHandle. 我已经将它与应用程序上下文一起使用了,但是我无法向SavedStateHandle它添加 a 。

这就是我所拥有的,只有应用程序上下文:

// 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)
Run Code Online (Sandbox Code Playgroud)

对于这个问题,我认为这可能会简化为:

// 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) 
Run Code Online (Sandbox Code Playgroud)

那么,对于还有一个SavedStateHandlein MyViewModel,我将如何修改片段中的调用(B1示例代码中的行)?我需要明确调用工厂SavedStateViewModelFactory吗?那究竟会是什么样子?(我还是 Kotlin/Android 的新手,我以前从未与工厂合作过)

Epi*_*rce 6

编辑:AndroidX-Activity 1.2.0and的最终版本中AndroidX-Fragment 1.1.0,他们SavedStateViewModelFactory在 AppCompatActivity/Fragment 中创建了默认工厂,因此不需要覆盖默认工厂(这是这个答案的后半部分所做的。)

更新然后使用

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

class MyAndroidViewModel(application: Application, val savedStateHandle: SavedStateHandle): AndroidViewModel(application)
Run Code Online (Sandbox Code Playgroud)

应该只是工作。


原来的:

我将如何修改片段中的调用(示例代码中的 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());
+    }
+
Run Code Online (Sandbox Code Playgroud)

这意味着如果我有 aBaseActivity或 a BaseFragment,我可以把它换成SavedStateViewModelFactoryfrom 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())
}
Run Code Online (Sandbox Code Playgroud)

一旦你有了它,你就可以依靠 ViewModel 的自动实例化SavedStateHandle作为它们的参数之一:

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

class MyAndroidViewModel(application: Application, val savedStateHandle: SavedStateHandle): AndroidViewModel(application)
Run Code Online (Sandbox Code Playgroud)

请注意,该订单application, savedStateHandle是由 预期的SavedStateViewModelFactory

但是,如果您确实需要除此之外的自定义参数,那么您必须object: AbstractSavedStateViewModelFactory在调用该ViewModelProvider(viewModelStoreOwner).get(...)方法时提供