diff --git a/voyager-hilt/build.gradle.kts b/voyager-hilt/build.gradle.kts index e7232e16..6ad02e05 100644 --- a/voyager-hilt/build.gradle.kts +++ b/voyager-hilt/build.gradle.kts @@ -27,6 +27,7 @@ dependencies { implementation(libs.lifecycle.savedState) implementation(libs.lifecycle.viewModelKtx) implementation(libs.hilt.android) + implementation(libs.lifecycle.viewModelCompose) kapt(libs.hilt.compiler) testRuntimeOnly(libs.junit.engine) diff --git a/voyager-hilt/src/main/java/cafe/adriel/voyager/hilt/ViewModel.kt b/voyager-hilt/src/main/java/cafe/adriel/voyager/hilt/ViewModel.kt index f35ff51a..90385fe7 100644 --- a/voyager-hilt/src/main/java/cafe/adriel/voyager/hilt/ViewModel.kt +++ b/voyager-hilt/src/main/java/cafe/adriel/voyager/hilt/ViewModel.kt @@ -3,11 +3,12 @@ package cafe.adriel.voyager.hilt import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalLifecycleOwner +import androidx.lifecycle.HasDefaultViewModelProviderFactory import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelStore -import cafe.adriel.voyager.androidx.AndroidScreenLifecycleOwner -import cafe.adriel.voyager.core.lifecycle.ScreenLifecycleProvider +import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.hilt.internal.componentActivity @@ -25,19 +26,26 @@ public inline fun Screen.getViewModel( viewModelProviderFactory: ViewModelProvider.Factory? = null ): T { val context = LocalContext.current + val lifecycleOwner = LocalLifecycleOwner.current + val viewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) { + "No ViewModelStoreOwner was provided via LocalViewModelStoreOwner" + } return remember(key1 = T::class) { - val activity = context.componentActivity - val lifecycleOwner = (this as? ScreenLifecycleProvider) - ?.getLifecycleOwner() as? AndroidScreenLifecycleOwner - ?: activity + val hasDefaultViewModelProviderFactory = requireNotNull(lifecycleOwner as? HasDefaultViewModelProviderFactory) { + "$lifecycleOwner is not a androidx.lifecycle.HasDefaultViewModelProviderFactory" + } + val viewModelStore = requireNotNull(viewModelStoreOwner?.viewModelStore) { + "$viewModelStoreOwner is null or have a null viewModelStore" + } val factory = VoyagerHiltViewModelFactories.getVoyagerFactory( - activity = activity, - delegateFactory = viewModelProviderFactory ?: lifecycleOwner.defaultViewModelProviderFactory + activity = context.componentActivity, + delegateFactory = viewModelProviderFactory + ?: hasDefaultViewModelProviderFactory.defaultViewModelProviderFactory ) val provider = ViewModelProvider( - store = lifecycleOwner.viewModelStore, + store = viewModelStore, factory = factory, - defaultCreationExtras = lifecycleOwner.defaultViewModelCreationExtras + defaultCreationExtras = hasDefaultViewModelProviderFactory.defaultViewModelCreationExtras ) provider[T::class.java] } diff --git a/voyager-hilt/src/main/java/cafe/adriel/voyager/hilt/internal/ContextExt.kt b/voyager-hilt/src/main/java/cafe/adriel/voyager/hilt/internal/ContextExt.kt index 88659969..e30bf818 100644 --- a/voyager-hilt/src/main/java/cafe/adriel/voyager/hilt/internal/ContextExt.kt +++ b/voyager-hilt/src/main/java/cafe/adriel/voyager/hilt/internal/ContextExt.kt @@ -5,9 +5,7 @@ import android.content.ContextWrapper import androidx.activity.ComponentActivity import androidx.lifecycle.ViewModelProvider -// Unfortunately findOwner function is internal in activity-compose -// TODO: Maybe move to androidx module because we'll need this function when implement onCloseRequest support -internal inline fun findOwner(context: Context): T? { +private inline fun findOwner(context: Context): T? { var innerContext = context while (innerContext is ContextWrapper) { if (innerContext is T) { @@ -22,7 +20,3 @@ internal inline fun findOwner(context: Context): T? { internal val Context.componentActivity: ComponentActivity get() = findOwner(this) ?: error("Context must be a androidx.activity.ComponentActivity. Current is $this") - -@PublishedApi -internal val Context.defaultViewModelProviderFactory: ViewModelProvider.Factory - get() = componentActivity.defaultViewModelProviderFactory