I am implementing a Navigation Controller for my app: https://developer.android.com/guide/navigation/navcontroller.
I defined the following Screen interface with some instances of it:
interface Screen {
/**
* Unique name to define the path for a composable
*/
val route: String
/**
* String resource id to that contains title to be displayed for the screen.
*/
val title: Int
}
object WelcomeDestination : Screen {
override val route = "welcome"
override val title = R.string.app_name
}
object AnotherDestination : Screen {
override val route = "another"
override val title = R.string.title_another
}
I define the app with the viewController and the navController. Then, I want to get the current screen instance from the navigation controller using toRoute():
@Composable
fun MyApp(
navController: NavHostController = rememberNavController(),
) {
val backStackEntry by navController.currentBackStackEntryAsState()
val currentScreen : Screen = backStackEntry?.toRoute<Screen>() ?: WelcomeDestination
}
But I am getting this error in execution time:
java.lang.IllegalArgumentException: Polymorphic value has not been read for class null
I think it could be because I'm using object instances, so maybe I should change my implementation to a @Serializable class
with data object
and data class
inside that class for every Screen option? But I'm not actually sure if that would solve the problem.
I would like to know the standard and proper way to implement this.
So far, the best approach I found is to create a Map that links the last route that backStackEntry
has with the corresponding Screen instance:
val screensByRoute : Map<String, Screen> =
mapOf(
WelcomeDestination.route to WelcomeDestination,
AnotherDestination.route to AnotherDestination
)
So now I can get the currentScreen instance with:
val currentScreen : Screen = screensByRoute[backStackEntry?.destination?.route] ?: WelcomeDestination
Although, I'm still a bit surprised that there is no any method, something like toRoute(), to get directly that Screen instance directly.