AndroidViewModel with SavedState

心不动则不痛 提交于 2020-04-16 02:47:23

问题


I need to use an AndroidViewModel with application context and a SavedStateHandle. I have it already working with application context, but I fail adding a SavedStateHandle to it.

This is what I have, with only the application context:

// 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)

I assume for this question this could likely be reduced to:

// 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) 

So, for also having a SavedStateHandle in MyViewModel, 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? (I am still new to Kotlin/Android, I've never worked with a factory before)


回答1:


EDIT: in the final release of AndroidX-Activity 1.2.0 and AndroidX-Fragment 1.1.0, they made SavedStateViewModelFactory the default factory in AppCompatActivity/Fragment, so it is not needed to override the default factory (which is what the second half of this answer does.)

Updating and then using

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

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

Should just work.


ORIGINAL:

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?

In AndroidX-Activity 1.2.0, they added a new method called 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());
+    }
+

Which means if I have a BaseActivity or a BaseFragment, I can swap this out for the SavedStateViewModelFactory from 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())
}

Once you have that, you can rely on the automatic instantiation of ViewModel with SavedStateHandle as one of their arguments:

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

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

Beware that the order application, savedStateHandle is expected by SavedStateViewModelFactory.

However, if you do need custom arguments on top of that, then you'd have to provide a object: AbstractSavedStateViewModelFactory when you invoke the ViewModelProvider(viewModelStoreOwner).get(...) method



来源:https://stackoverflow.com/questions/61063844/androidviewmodel-with-savedstate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!