I need to pass a Song
object from HomePage
to PlayerPage
. Now I have already created a somewhat tolerable routing mechanism. Since I have both bottom navigation and full-screen pages in my application.
Right now I am facing an issue with passing objects through navigation. I have already referred to this and this guide. But cannot connect the dots between the answer and my existing navigation.
I have created a Router
interface:
interface Router {
fun openHome()
fun openAlbumPage()
fun openNotification()
fun openSettings()
fun openPlayer()
fun openSearchPage()
fun goBack()
fun <T: Any> getArgs(tag: String): T?
}
and the implementation is as:
class RouterImpl (
private val navHostController: NavHostController,
private val startDestination: String = HOME
) : Router {
override fun openHome() {
navigate(Page.Home, removeFromHistory = true, singleTop = true)
}
.....
override fun openPlayer() {
navigate(Page.Player)
}
private fun navigate(
page : Page,
removeFromHistory : Boolean = false,
singleTop: Boolean = false
){
navHostController.apply {
navigate(page.route){
if(removeFromHistory){
if(singleTop){
popUpTo(Page.Home.route)
}else{
popUpTo(0){
saveState = false
}
}
} else{
restoreState = true
}
launchSingleTop = singleTop
}
}
}
override fun goBack() {
navHostController.apply {
navigateUp()
navigate(startDestination){
launchSingleTop = true
restoreState = true
}
}
}
private fun checkArgsAndNavigate(it: Any?, page: Page): () -> Unit = {
it?.let {
navHostController.putArgs(Pair(page.tag, it))
}
navigate(page)
}
@SuppressLint("LongLogTag")
override fun <T: Any> getArgs(tag: String): T? {
return try{
navHostController.previousBackStackEntry?.arguments?.get(tag) as T?
} catch (ex: Exception){
Log.d("Exception from getArgs: ", ex.toString())
null
}
}
}
I usually pass the router object to desired buttons and just call the associated method: router.openPlayerPage
.
Inside my NavigationContainer
:
fun NavigationContainer(
router: Router,
navController: NavHostController,
paddingValues: PaddingValues
){
val startDestination = remember { mutableStateOf(Page.Splash.route) }
LaunchedEffect(startDestination){
if(startDestination.value == Page.Home.route){
router.openHome()
}
}
NavHost(
navController = navController,
startDestination = startDestination.value
){
composable(Page.Splash.route){
SplashPage(
goBack = {
startDestination.value = Page.Home.route
}
)
}
/*
Bottom Navigation Bar
*/
composable(Page.Home.route){
HomePage(router)
}
composable(Page.Favorite.route){
FavoritePage()
}
composable(Page.Profile.route){
ProfilePage()
}
/*
=============================================
*/
composable(Page.Player.route, Song song){ // unresolved reference: song
PlayerPage(song = song)
}
composable(Page.Search.route){
SearchPage()
}
}
}
I was thinking of sending the object to desired composable using bacStackEntry rather than converting it to json string and passing it as a string.
How can I solve this issue? thanks.
The full code is available here