Anyone in here using KMM ViewModel? Trying to a cr...
# kotlin-inject
b
Anyone in here using KMM ViewModel? Trying to a create an extension function similar to hiltViewModel() that caches vm instances
was able to get this to work via:
Copy code
@Composable
inline fun <reified T : ScreenModel> Screen.screenViewModel(
    crossinline factory: @DisallowComposableCalls () -> T = {
        with (ViewModelComponent::class.create()) {
            getViewModel<T>()
        } as T
    }
): T = this.rememberScreenModel(tag = T::class.qualifiedName) { factory() }
with ViewModelComponent being:
Copy code
@Component
abstract class ViewModelComponent: AppComponent() {
    abstract val loginViewModel: LoginViewModel
    abstract val homeViewModel: HomeViewModel

    inline fun <reified T: ScreenModel> getViewModel(): ScreenModel {
        return when (val clazz = T::class) {
            LoginViewModel::class -> loginViewModel
            HomeViewModel::class -> homeViewModel
            else -> throw NoSuchElementException("No viewModel found for ${clazz.simpleName}")
        }
    }
}
👀 2
now I can
Copy code
@Composable
private fun Screens.Home.Content(
    modifier: Modifier = Modifier,
    viewModel: HomeViewModel = screenViewModel()
) {
d
What does
rememberScreenModel
do? I've done something similar but no remember calls (mainly because Hilt didn't seem to use remember)
Copy code
@Composable
inline fun <reified VM : ViewModel, reified F: ViewModelFactory<VM>> kotlinInjectViewModel(
    factory: (ApplicationComponent) -> F,
    viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
        "No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
    },
): VM {
    val context = LocalContext.current
    val component = factory(context.applicationComponent)
    return viewModel(
        viewModelStoreOwner = viewModelStoreOwner,
        factory = component.factory()
    )
}
b
rememberScreenModel is available from voyager navigation which is:
Copy code
@Composable
public inline fun <reified T : ScreenModel> Screen.rememberScreenModel(
    tag: String? = null,
    crossinline factory: @DisallowComposableCalls () -> T
): T =
    remember(ScreenModelStore.getKey<T>(this, tag)) {
        ScreenModelStore.getOrPut(this, tag, factory)
    }
Similar concept to what you have setup when boiled down