Cannot resolve ViewModelProvider construction in a fragment?

后端 未结 4 1794
悲哀的现实
悲哀的现实 2021-02-19 05:28

I have been spending a lot of time trying to figure out why in the code below (towards the end), I get an error on ViewModelProvider(this). I also tried getActivity() instead of

相关标签:
4条回答
  • 2021-02-19 05:43

    The cleanest implementation must use Kotlin for its advanced functions. You can either create this kotlin code in a separate Kclass or leave this answer for future users that want to know how to do this in Kotlin. Basically we are initialising the ViewModel by lazy like this:

    Make sure you have this dependency:

    implementation "androidx.fragment:fragment-ktx:1.2.0"
    

    Create this helper function that accesses an internal fragment-ktx method that allows yo to create a ViewModel instance by lazy:

    @MainThread
    inline fun <reified VM : ViewModel> Fragment.fragmentViewModel() =
        createViewModelLazy(
            VM::class,
            { this.viewModelStore },
            { ViewModelFactory(Database.getDatabase(requireContext().applicationContext)) }
        )
    

    Now create a ViewModelFactory using this official java example:

    https://github.com/android/architecture-components-samples/blob/master/BasicRxJavaSample/app/src/main/java/com/example/android/observability/ui/ViewModelFactory.java

    Or, here is the Kotlin variant:

    class ViewModelFactory(private val database: Database?) : ViewModelProvider.Factory {
    
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
    
            requireNotNull(database) { "Database must not be null" }
    
            return when {
    
                modelClass.isAssignableFrom(ItemSetupFragmentModel::class.java) -> {
                    ItemSetupFragmentModel() as T
                }
    
                else -> {
                    throw IllegalArgumentException("Unknown ViewModel class")
                }
            }
        }
    }
    

    And now go inside your fragment and simply initialise your ViewModel like this

    class ItemSetupFragment : Fragment() {
    
        private val model by viewModel<ItemSetupFragmentModel>()
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
    
            model.getKids().observe(this, users -> {
                // update UI
            });
        }
    }
    

    Hope this helps!

    0 讨论(0)
  • 2021-02-19 05:48

    Firstly you need to use the latest version of lifecycle extension. It should be:

    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0" 
    

    or any updated version.

    Then you should use requireActivity() instead of getActivity(). This way you will ensure that the activity is attached an not getting a NullPointerException.

    ItemSetupFragmentModel model = new ViewModelProvider(requireActivity()).get(ItemSetupFragmentModel.class);
    

    Note: ViewModel Overview and Declaring Dependencies

    I had to restart cache after adding the library to the Gradle file. There is no need to use requireActivity(), this is enough.

    0 讨论(0)
  • 2021-02-19 05:56

    You aren't using the latest library release in which the ViewModelProvider(@NonNull ViewModelStoreOwner owner) constructor was included. You are seeing the latest docs but not using the latest library version of ViewModel. You need to use

        implementation 'androidx.lifecycle:lifecycle-viewmodel:2.2.0' // For Java
    

    or

        implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' // For kotlin extension
    
    0 讨论(0)
  • 2021-02-19 06:00

    You should instantiate your viewModel by :

    ItemSetupFragmentModel model = ViewModelProviders.of(this).get(ItemSetupFragmentModel.class);
    
    0 讨论(0)
提交回复
热议问题