Compose Navigation:检查当前路由匹配数据对象及混淆后的替代方案
在使用Compose Navigation时,常通过序列化数据对象定义路由:
@Serializable data object HomeRoute composable<HomeRoute> { entry -> HomeRoute(...) }
原本通过对比类名检查当前路由的逻辑,在Debug构建下正常,但开启isMinifyEnabled = true的Release构建中,HomeRoute类名会被混淆,而导航路由名称保持原类名,导致对比失效:
currentBackStackEntry: com.example.app.home.navigation.HomeRoute vs P5.d, false
虽然添加@Keep注解可以解决问题,但以下是几种无需保留类名的路由匹配替代方法:
方法1:类型安全解析导航参数
直接通过导航Entry的参数解析来判断当前路由类型,避开字符串类名对比:
val currentBackStackEntry = navController.currentBackStackEntryAsState() LaunchedEffect(currentBackStackEntry.value) { val isHomeRoute = currentBackStackEntry.value?.arguments?.let { args -> runCatching { args.navArgs<HomeRoute>() true }.getOrDefault(false) } ?: false Timber.d("当前是否为HomeRoute: $isHomeRoute") }
这种方式依赖Compose Navigation的类型安全参数机制,即便类名被混淆,仍能正确识别对应的路由类型。
方法2:自定义固定路由名称
定义路由时手动指定固定字符串,完全脱离类名依赖:
@Serializable data object HomeRoute { const val ROUTE_NAME = "home_route" } // 注册路由时指定自定义名称 composable(route = HomeRoute.ROUTE_NAME) { entry -> HomeRoute(...) } // 对比时直接使用固定名称 val currentBackStackEntry = navController.currentBackStackEntryAsState() val route = currentBackStackEntry.value?.destination?.route LaunchedEffect(route) { val isHomeRoute = route == HomeRoute.ROUTE_NAME Timber.d("当前是否为HomeRoute: $isHomeRoute") }
这种方式不受混淆影响,同时路由名称更直观可读。
方法3:通过Destination ID对比
每个导航Destination都有唯一ID,预先获取HomeRoute对应的ID后,直接对比ID判断:
// 注册路由后保存对应的Destination ID val homeDestinationId = remember { navController.graph.findNode<HomeRoute>()?.id ?: -1 } // 对比时使用ID判断 val currentBackStackEntry = navController.currentBackStackEntryAsState() LaunchedEffect(currentBackStackEntry.value) { val isHomeRoute = currentBackStackEntry.value?.destination?.id == homeDestinationId Timber.d("当前是否为HomeRoute: $isHomeRoute") }
这种方式完全依赖导航组件内部的唯一标识,不受类名混淆、字符串变化的影响。
内容的提问来源于stack exchange,提问作者user924
相关产品推荐
相关产品推荐

