How android shares VMs with arguments in the constructor between Activity and Fragment

Asked 2 years ago, Updated 2 years ago, 81 views

I want to handle sharedViewModel.The VM receives arguments in the constructor.
How can I call this with viewModels or activityViewModels?

class MyViewModel (vala:Int):ViewModel(){
  class Factory constructor (private value:Int):ViewModelProvider.Factory {
    override fun<T:ViewModel?>create(modelClass:Class<T>):T{
            @Suppress("UNCHECKED_CAST")
            return MyViewModel (this.a) as T
    }
  }
}

class MyActivity:AppCompatActivity(){
  // viewModels is fragment-ktx package
  valviewModel: MyViewModel by viewModels {MyViewModel.Factory(a=1)}
}

class MyFragment:Fragment(){
    valviewModel: MyViewModel by activityViewModels() // raise Cannot create an instance of class com.example.myapp.MyViewModel
}

android kotlin

2022-09-29 21:58

1 Answers

https://developer.android.com/reference/kotlin/androidx/fragment/app/package-summary?hl=ja#(androidx.fragment.app.Fragment).activityViewModels(kotlin.Function0)

Returns a property delete to access parent activity's ViewModel, if factoryProducer is specified then ViewModelProvider.Factory returned by it will be used to create ViewModel first time.Otherwise, the activity's android.activity.giftDevice.Compactivity

Google Translation

Returns the property delegate to access ViewModel for parent activity.If factoryProducer is specified, the ViewModelProvider.Factory returned by it is used to create the first ViewModel. Otherwise, the activity androidx.activity.ComponentActivity.getDefaultViewModelProviderFactory will be used.

Therefore, I suspect that the following nano is the cause of the error.

  • Fragment ViewModel retrieval was preceded by Activity ViewModel retrieval
  • Activity has not yet acquired ViewModel, so activityViewModels in Fragment are responsible for creating the first viewModel
  • Fragment activityViewModels have no arguments, so you want to create a ViewModel using the parent activity getDefaultViewModelProviderFacility
  • The parent Activity getDefaultViewModelProviderFacility remains the default, not the custom Factory (it appears that using viewModels does not change the defaultViewModelProviderFactory)
  • The default ViewModelProviderFacyory fails to generate instance if ViewModel::class with argument is specified

Change Activity's etDefaultViewModelProviderFacilities to override and return custom's Factory

class MyViewModel (vala:Int):ViewModel(){
  class Factory constructor (private value:Int):ViewModelProvider.Factory {
    override fun<T:ViewModel?>create(modelClass:Class<T>):T{
            @Suppress("UNCHECKED_CAST")
            return MyViewModel (this.a) as T
    }
  }
}

class MyActivity:AppCompatActivity(){
  // viewModels is fragment-ktx package
-  valviewModel: MyViewModel by viewModels {MyViewModel.Factory(a=1)}
+  valviewModel: MyViewModel by viewModels()

+  override fungetDefaultViewModelProviderFactory():ViewModelProvider.Factory{
+    return MyViewModel.Factory(a=1)
+  }
}

class MyFragment:Fragment(){
    valviewModel: MyViewModel by activityViewModels()//Successful! And shared!

}


2022-09-29 21:58

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.