accompanist icon indicating copy to clipboard operation
accompanist copied to clipboard

[Navigation Animation] viewmodel leaks when screen forces certain orientation (rotation)

Open arunjoseph-tomtom opened this issue 2 years ago • 0 comments

Description I observe that the obtained viewmodel leaks when transitions between screens, when each screen forces certain orientation. Sample code below.

class AppActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            SampleNavHost()
        }
    }
}

@Composable
fun SampleNavHost() {
    val navController = rememberAnimatedNavController()
    AnimatedNavHost(
        navController = navController,
        startDestination = "ScreenA",
    ) {
        composable("ScreenA") {
            val viewModel: ScreenAViewModel = viewModel()
            val context = LocalContext.current
            LaunchedEffect(key1 = Unit) {
                context.tryFindActivity()?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
            }
            Button(
                onClick = {
                    navController.popBackStack()
                    navController.navigate("ScreenB")
                },
                content = {
                    Text("Navigate to ScreenB")
                }
            )
        }
        composable("ScreenB") {
            val viewModel: ScreenBViewModel = viewModel()
            val context = LocalContext.current
            LaunchedEffect(key1 = Unit) {
                context.tryFindActivity()?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
            }
            Button(
                onClick = {
                    navController.popBackStack()
                    navController.navigate("ScreenA")
                },
                content = {
                    Text("Navigate to ScreenA")
                }
            )
        }
    }
}

class ScreenAViewModel : ViewModel() {
    override fun onCleared() {
        println("onCleared $this")
        super.onCleared()
    }
    init {
        println("onCreated $this")
    }
}

class ScreenBViewModel : ViewModel() {
    override fun onCleared() {
        println("onCleared $this")
        super.onCleared()
    }
    init {
        println("onCreated $this")
    }
}

fun Context.tryFindActivity(): Activity? {
    var context = this
    while (context is ContextWrapper) {
        if (context is Activity) return context
        context = context.baseContext
    }
    return null
}

Steps to reproduce Click button to transition between ScreenA to ScreenB. Logcat shows

2022-07-28 08:48:02.868 15669-15669 System.out                                           I  onCreated com.tomtom.roadcaptain.home.presentation.ScreenAViewModel@66faa0b
2022-07-28 08:48:05.696 15669-15669 System.out                                           I  onCreated com.tomtom.roadcaptain.home.presentation.ScreenBViewModel@5b834d9
2022-07-28 08:48:14.797 15669-15669 System.out                                           I  onCreated com.tomtom.roadcaptain.home.presentation.ScreenAViewModel@1ef23a5 

Expected behavior

2022-07-28 08:38:22.523 14687-14687 System.out                                           I  onCreated com.tomtom.roadcaptain.home.presentation.ScreenAViewModel@30e43db
2022-07-28 08:38:25.694 14687-14687 System.out                                           I  onCreated com.tomtom.roadcaptain.home.presentation.ScreenBViewModel@7939130
2022-07-28 08:38:26.428 14687-14687 System.out                                           I  onCleared com.tomtom.roadcaptain.home.presentation.ScreenAViewModel@30e43db
2022-07-28 08:38:45.367 14687-14687 System.out                                           I  onCreated com.tomtom.roadcaptain.home.presentation.ScreenAViewModel@a2852cc
2022-07-28 08:38:46.084 14687-14687 System.out                                           I  onCleared com.tomtom.roadcaptain.home.presentation.ScreenBViewModel@7939130

I get this when I use just the NavHost in place of AnimatedNavHost Additional context Tested with version 0.24.13-rc

arunjoseph-tomtom avatar Jul 28 '22 07:07 arunjoseph-tomtom