m

    MaxUt

    1 year ago
    Hi there, I'm using Hilt to inject dependencies. I was wondering if it's possible to instanciate an object which contains depencies (injected with Hilt) in a Composable ?
    I was expecting to able to do something like this :
    class SearchViewManager @Inject constructor(
        val catalogManager: CatalogManager,
        private val _widgetManager: WidgetsManager
    ) { 
        ... 
    }
    
    @Composable
    fun SearchScreen() {
        val searchViewManager: SearchViewManager = SearchViewManager()
    }
    However, it seems like I have to pass the parameters.
    Colton Idle

    Colton Idle

    1 year ago
    I pass a ScreenViewModel into my Screen, but it's all setup via hilt and
    hiltViewModel()
    See: https://developer.android.com/jetpack/compose/libraries#hilt
    m

    MaxUt

    1 year ago
    @Colton Idle thanks for the tip. Is there a way to have one view model per instance of a composable ? The idea is that I don't want to share the same viewModel instance across SearchScreen composable. For now I instanciated 3 SearchViewManager in the MainActivity that I pass down to the different SearchScreen composable via parameters but I find this solution a bit complicated. Any idea ?
    Colton Idle

    Colton Idle

    1 year ago
    I still don't feel comfortable with answering this (don't want to misinform). May want to wait for someone else to chime in on the scoping question. Maybe/hopefully Ian Lake can chime in. He's always helpful 😄
    m

    MaxUt

    1 year ago
    😀 thank you
    Tgo1014

    Tgo1014

    1 year ago
    There isn’t yet scope for injection. Here is the feature request, theres a workaround on it: https://issuetracker.google.com/issues/165642391
    Colton Idle

    Colton Idle

    1 year ago
    As far as I know (I could be wrong), the ViewModel scope will always outlive the screen and be shared if you have multiple of those screens visible. So lets say you had ScreenAViewModel and then
    Column{
    ScreenA
    ScreenA
    }
    then whatever change you make in the top screenA, should also be shown in the bottom screenA.
    m

    MaxUt

    1 year ago
    Yes exactly, from what I understood the viewModel is tied to the lifecycle of the Activity. In my case I'd like to have multiple instance of a viewModel.
    Colton Idle

    Colton Idle

    1 year ago
    Looks like maybe this is handled with compose nav? As per that issue "Ian, I believe this is covered with navigation. Can you confirm and close?"
    Tgo1014

    Tgo1014

    1 year ago
    I guess if you navigate from one screen to another you can do it with the nav scope. My case with pagers doesn’t work very well as the screens are “alive” at same time
    m

    MaxUt

    1 year ago
    Right, the navigation might do the trick. I'm a bit in the same situation as you @Tgo1014, I'm not using the standard navigation library (I need slideIn/Out transition which haven't been released yet)
    Tgo1014

    Tgo1014

    1 year ago
    m

    MaxUt

    1 year ago
    Wow amazing, I didn't see it coming 🙂
    Colton Idle

    Colton Idle

    1 year ago
    https://medium.com/androiddevelopers/animations-in-navigation-compose-36d48870776b Just released yesterday. So you're finding out about it right on time. 😄
    k

    knthmn

    1 year ago
    @MaxUt idk if this is what you want, but you can pass
    key
    in
    hiltViewModel()
    (or
    viewModel()
    ) to get several viewmodels in the same scope.
    val a = viewModel<FooVM>(key = "1")
    val b = viewModel<FooVM>(key = "2")
    println(a === b) // false
    Tgo1014

    Tgo1014

    1 year ago
    @knthmn the problem with this is that it doesn’t inject automatically, so you have inject in the activity and pass everything as parameters, which works, but doesn’t look very clean
    k

    knthmn

    1 year ago
    use
    @HiltViewModel
    from
    com.google.dagger:hilt-android
    https://developer.android.com/training/dependency-injection/hilt-jetpack#viewmodels edit: I checked
    hiltViewModel()
    doesn't provide a
    key
    parameter, however you can copy the function and add the
    key
    parameter that is passed to
    viewModel()
    .
    Tgo1014

    Tgo1014

    1 year ago
    @knthmn with hilt you need to use
    hiltViewModel<T>()
    which, afaik, doesn’t have a “key” parameters to define a scope
    k

    knthmn

    1 year ago
    check my edit above, the only thing
    hiltViewModel()
    does is hook in the factory for creating the vm, i think it is safe to add a key parameter to it.
    Tgo1014

    Tgo1014

    1 year ago
    I’m trying it now, will report back in a few minutes
    Doesn’t work:
    java.lang.IllegalArgumentException: SavedStateProvider with the given key is already registered
    k

    knthmn

    1 year ago
    Sorry I didn't verify and got your hopes up. They changed how it is implemented.https://github.com/google/dagger/issues/2328 This worked when it used to be
    @ViewModelInject
    (which I used a few months ago)