I'm learning Kotlin and I have a viewModel which is created as navGraphViewModels().
private val viewModel: CreationSignalementViewModel by navGraphViewModels(R.id.creation_signalement_nav_graph)
I would like to know if it's possible to add a ViewModelFactory to this viewModel declaration ?
thank you :)
Related
error: cannot find symbol
MainActivityViewModel model = ViewModelProvider(this).get(MainActivityViewModel.class);
I tried different solutions available but no luck for me.
You can create a view model using the by ViewModels() kotlin property delegate:
private val viewModel: YourCustomViewModel by viewModels()
or you can use ViewModelProvider to create ViewModels and retain them in a store of the given ViewModelStoreOwner.
Check the official documentation for best practices:
https://developer.android.com/reference/androidx/lifecycle/ViewModelProviders#of(androidx.fragment.app.Fragment)
https://developer.android.com/reference/androidx/lifecycle/ViewModelProvider#ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner)
Maybe I'm blind but I can't find anything about injecting a dependency that needs parameters in side a composable using dagger hilt.
Lets say my ViewModel looks something like this:
class MyViewModel #AssistedInject constructor(#Assisted myValue: Int) : ViewModel() {
...
}
and I've got a factory interface like this:
#AssistedFactory
interface MyViewModelAssistedFactory {
fun create(myValue: Int): MyViewModel
}
how can I inject that dependency with a certain value as parameter?
All answers I found where like:
#Inject
var myViewModelFactory: MyViewModelAssistedFactory;
and
val initValue = 4
fun onCreate(){
val viewModel = myViewModelFactory.create(initValue)
}
but that doesn't work inside a composable fun.
Not sure if still relevant but if you use the navigation component you can just call hiltViewModel() in the navgraph builder.
Example:
https://github.com/pablichjenkov/ComposeStudy/blob/04298ca8393d3eea0f5b7883fb223161ef79a962/app/src/main/java/com/pablichj/study/compose/home/HomeNavigation.kt#L24
If not using Jetpack Navigation then the solution is a bit more complex. You will need to create a State tree in your App where they implement LifecycleOwner and ViewModelStoreOwner, in order to be able to install the ViewModel appropriately. The good news is that there is work out there already doing so, check this:
https://github.com/Syer10/voyager
just it's me trying to implement MVVM architecture with Kotlin. I need to use ViewModelProvider to init my instance and I'm getting this error...
Any advice?
You have a no of options to to instantiate viewmodels.
Now You can now use the ViewModelProvider constructor directly.
private val assignmentViewModel= ViewModelProvider(this).get(AssignmentViewModel::class.java)
If you use androidx.activity:activity-ktx:$Version in the library you can do this directly
private val assignmentViewModel: AssignmentViewModel by viewModels()
If you're using a viewModelFactory
private val assignmentViewModel= ViewModelProvider(this, viewModelFactory).get(AssignmentViewModel ::class.java)
and private val assignmentViewModel: AssignmentViewModel by viewModels { viewModelFactory } respectively
If you're using Kotlin the easiest way to incorporate a ViewModel in your code is via a property delegate:
Activity/Fragment:
val assignmentViewModel: AssignmentViewModel by viewModels()
Fragment:
val assignmentViewModel: AssignmentViewModel by activityViewModels()
The latter allows you to share data between fragments, since activityViewModels scopes it to the Activity.
See ViewModel Overview for more information.
I'm following Kotlin tutorial on learning Dagger Hilt for dependency injection. The tutorial uses
class MainActivity: AppCompatActivity() {
private val viewModel: TestViewModel by viewModels()
}
in the MainActivity to inject the viewmodel.
It requires a dependency: implementation "androidx.activity.activity-ktx:1.1.0" to do so.
I'm trying to learn hilt in Java so I'm unsure what the Java equivalent of injecting the viewmodel into my activity is.
This is incorrect and doesn't work
#Inject
private TestViewModel testViewModel;
and using
testViewModel = new ViewModelProvider(this).get(TestViewModel.class);
doesn't seem like dependency injection.
What is the equivalent of by viewModels() in Java?
testViewModel = new ViewModelProvider(this).get(TestViewModel.class) is indeed exactly what by viewModels() does for you.
You'll note that both by viewModels() and new ViewModelProvder(this) don't pass in a custom ViewModelProvider.Factory instance - that's because they use the default Factory - the one setup by Hilt to correctly create your ViewModel via DI.
I have single activity application and number of fragments. Some of these fragments are using my viewmodel, typically like this:
private val myViewModel: MyViewModel by sharedViewModel()
What if I want to have the model both shared and keep its state with SavedStateHandle? I cannot figure out if this is supported and if so, how it needs to be used (declaring viewmodel as stateViewModel in hosting activity is not working).
Update: as koin 2.1.6 is around, they introduced org.koin.androidx.viewmodel.ext.android.stateSharedViewModel that you can use in your fragments.
Ok after an hour of digging Koin samples and figuring out a few gotchas:
Assuming your view model is something similar to this:
class SavedStateViewModel(val handle: SavedStateHandle, val service: SimpleService)
...and your DI looks like this:
viewModel { (handle: SavedStateHandle) -> SavedStateViewModel(handle, get()) }
Your shared state view model can be consumed in your fragments like this:
val sharedSaved: SavedStateViewModel by sharedViewModel()
(important!) You need this declaration in your activity:
lateinit var savedVm: SavedStateViewModel
(important) You need to call this right after super.onCreate(savedInstanceState) in your activity:
savedVm = getStateViewModel()
It is important not to use lazy version for the above (stateViewModel).