Skip to content

Commit

Permalink
fix: hilt viewmodel onCleared not called (#242)
Browse files Browse the repository at this point in the history
  • Loading branch information
DevSrSouza authored Oct 31, 2023
1 parent 1aef8ae commit 4b8d121
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 17 deletions.
1 change: 1 addition & 0 deletions voyager-hilt/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
28 changes: 18 additions & 10 deletions voyager-hilt/src/main/java/cafe/adriel/voyager/hilt/ViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -25,19 +26,26 @@ public inline fun <reified T : ViewModel> 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]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <reified T> findOwner(context: Context): T? {
private inline fun <reified T> findOwner(context: Context): T? {
var innerContext = context
while (innerContext is ContextWrapper) {
if (innerContext is T) {
Expand All @@ -22,7 +20,3 @@ internal inline fun <reified T> findOwner(context: Context): T? {
internal val Context.componentActivity: ComponentActivity
get() = findOwner<ComponentActivity>(this)
?: error("Context must be a androidx.activity.ComponentActivity. Current is $this")

@PublishedApi
internal val Context.defaultViewModelProviderFactory: ViewModelProvider.Factory
get() = componentActivity.defaultViewModelProviderFactory

0 comments on commit 4b8d121

Please sign in to comment.