Not sure the best place to put this, but I'll put ...
# compose-android
c
Not sure the best place to put this, but I'll put it in compose-android for now because it touches on compose-navigation + Hilt + ViewModels. I really like the integration between all three. Injecting dependencies into VMs is super easy. i love it. But... I wanna try to go the KMP + compose route. has anyone migrated a hilt + VM + compose nav app to kmp compose yet? If so, what stack of libraries do you recommend there? I think I wanna go the "precompose" library route because it has navigation and VMs that are basically identical to Android... but DI is my last issue. Whats best to use there that doesn't require me to completely relearn a new DI library?
l
#kotlin-inject has a fairly similar syntax to Dagger if that's what you value
c
Wonder if its easy to integrate with precompose viewmodel
l
I am not familiar with precompose, but since you use Jetpack ViewModel, maybe this would be interesting to you? https://github.com/rickclephas/KMM-ViewModel
d
@Colton Idle I'm doing a similar transition from Hilt to Kotlin Inject (although I don't plan to share my view layer, prefer native UI), have you managed to come up with a neat way to have something similar to hilt's viewmodel helper function? It seems like a ton of boilerplate is needed and I'm not sure if my team will be particularly happy with that, am I missing a trick here?
c
im in the same boat. lol
i'm going precompose because i can basically move over my navigation and viewmodels with little work. but yeah. viewmodels are tricky because i love using them with hilt.
@Tlaster recommended https://mori-atsushi.github.io/koject/ which i still have to checkout
i think i might go Koin though because its widely adopted. and even though i rather use real "DI" like dagger, i feel like koin might just be easier to get support. I'm thinking that i might convert my android app to koin first.
then i might start moving it into shared/commonMain
d
Yeah so this is pretty much what I've done now too - replaced Hilt with Kotlin Inject and everything was fine until I reached the viewmodel layer and more precisely, viewmodels with SavedStateHandle... We've already done a similar migration to Koin for a different app but I was really keen on trying kotlin-inject for this one..
👍 1
I got it to work (actually got it to compile and run but not sure if I've checked all VMs for crashes) but these view model factories are just meh..
Copy code
@Inject
class KotlinInjectViewModelFactory(
    private val fooViewModel: (SavedStateHandle) -> PaymentOverviewViewModel,
    private val barViewModel: () -> UsernamePasswordViewModel,
): ViewModelProvider.Factory {
    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel> create(
        modelClass: Class<T>,
        extras: CreationExtras
    ): T {
        val savedStateHandle = extras.createSavedStateHandle()
        return when (modelClass) {
            FooViewModel::class.java -> fooViewModel(savedStateHandle)
            BarViewModel::class.java -> barViewModel()
            else -> throw Exception("Unknown view model")
        } as T
    }
}

/**
 * Taken from docs: <https://github.com/evant/kotlin-inject/blob/main/docs/android.md#compose>
 * */
@Composable
inline fun <reified VM : ViewModel> kotlinInjectViewModel(
    viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
        "No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
    }
): VM {
    val context = LocalContext.current
    val component = ViewModelFactoryComponent::class.create(context.applicationComponent)
    return viewModel(
        viewModelStoreOwner = viewModelStoreOwner,
        factory = component.factory()
    )
}
c
yeah. my issue with the factory is that i have no idea whats going on and so its hard for me to feel confident about it.