iwmh’s blog

ただの書き散らし/メモ

Jetpack Composeのnavigation routeにURLを含めるときは、URLEncodeする必要がある

  • 失敗するコード ・NavigationGraph
@Composable
fun MainNavGraph(
        navController: NavHostController,
        modifier: Modifier = Modifier
){
    NavHost(
            navController = navController,
            startDestination = Screen.Home.route,
            modifier = modifier
    ){
        // このrouteにnavigateしたい
        composable(
            route = "${Screen.EpisodeDetail.route}/" +
                    "{" + Constants.nav_episodeName + "}/" +
                    "{" + Constants.nav_imageUrl + "}/" +
                    "{" + Constants.nav_description  + "}/" +
                    "{" + Constants.nav_duration + "}/" +
                    "{" + Constants.nav_releaseDate + "}",
            arguments = listOf(
                navArgument(Constants.nav_episodeName){
                    type = NavType.StringType
                },
                navArgument(Constants.nav_imageUrl){
                    type = NavType.StringType
                },
                navArgument(Constants.nav_description){
                    type = NavType.StringType
                },
                navArgument(Constants.nav_duration){
                    type = NavType.IntType
                },
                navArgument(Constants.nav_releaseDate){
                    type = NavType.StringType
                },
            )
        ){ navBackStackEntry ->
            val episodeName = navBackStackEntry.arguments?.getString(Constants.nav_episodeName)
            val imageUrl = navBackStackEntry.arguments?.getString(Constants.nav_imageUrl)
            val description = navBackStackEntry.arguments?.getString(Constants.nav_description)
            val duration = navBackStackEntry.arguments?.getInt(Constants.nav_duration)
            val releaseDate = navBackStackEntry.arguments?.getString(Constants.nav_releaseDate)
            EpisodeDetailScreen(
                episodeName = episodeName!!,
                imageUrl = imageUrl!!,
                description = description!!,
                duration = duration!!,
                releaseDate = releaseDate!!
            )
        }
    }

}

・遷移

@Composable
fun EpisodesScreen(
    navController: NavController,
    showId: String?
) {
    val viewModel: EpisodesScreenViewModel = hiltViewModel()
    // Hold the Show ID for this screen.
    // TODO: Needs better code here.
    viewModel.showId = showId

    val lazyPagingItems = viewModel.pagingFlow.collectAsLazyPagingItems()

    val isRefreshing by viewModel.isRefreshing.collectAsState()

    SwipeRefresh(
        state = rememberSwipeRefreshState(isRefreshing),
        onRefresh = {
            lazyPagingItems.refresh()
        }
    ) {
        Column {
            Text(text = "Episodes")
            Text(text = lazyPagingItems.itemCount.toString())
            LazyColumn {
                items(lazyPagingItems) { episodeItem ->
                    EpisodeCardSquare(
                        episodeName = episodeItem!!.name,
                        imageUrl = episodeItem!!.images[2].url,
                        description = episodeItem!!.description,
                        duration = episodeItem!!.duration_ms,
                        releaseDate = episodeItem!!.release_date,
                        // Navigate to episode-detail screen.
                        onClick = {
                            navController.navigate(
                                "${Screen.EpisodeDetail.route}/" +
                                        "${episodeItem!!.name}/" +
                                        "${episodeItem!!.images[2].url}/" +
                                        "${episodeItem!!.description}/" +
                                        "${episodeItem!!.duration_ms}/" +
                                        "${episodeItem!!.release_date}"
                            )
                        }
                    )
                }
            }
        }
    }
}
  • 修正後コード ・NavigationGraphは変更なし ・遷移元
@Composable
fun EpisodesScreen(
    navController: NavController,
    showId: String?
) {
    val viewModel: EpisodesScreenViewModel = hiltViewModel()
    // Hold the Show ID for this screen.
    // TODO: Needs better code here.
    viewModel.showId = showId

    val lazyPagingItems = viewModel.pagingFlow.collectAsLazyPagingItems()

    val isRefreshing by viewModel.isRefreshing.collectAsState()

    SwipeRefresh(
        state = rememberSwipeRefreshState(isRefreshing),
        onRefresh = {
            lazyPagingItems.refresh()
        }
    ) {
        Column {
            Text(text = "Episodes")
            Text(text = lazyPagingItems.itemCount.toString())
            LazyColumn {
                items(lazyPagingItems) { episodeItem ->
                    EpisodeCardSquare(
                        episodeName = episodeItem!!.name,
                        imageUrl = episodeItem!!.images[2].url,
                        description = episodeItem!!.description,
                        duration = episodeItem!!.duration_ms,
                        releaseDate = episodeItem!!.release_date,
                        // Navigate to episode-detail screen.
                        onClick = {
                        // URLが含まれる情報をURLEncodeしてから、navController.navitateに渡す。 
                            val encodedImageUrl
                                    = URLEncoder.encode(episodeItem!!.images[2].url, StandardCharsets.UTF_8.toString())
                            val encodedDescription
                                    = URLEncoder.encode(episodeItem!!.description, StandardCharsets.UTF_8.toString())
                            navController.navigate(
                                "${Screen.EpisodeDetail.route}/" +
                                        "${episodeItem!!.name}/" +
                                        "${encodedImageUrl}/" +
                                        "${encodedDescription}/" +
                                        "${episodeItem!!.duration_ms}/" +
                                        "${episodeItem!!.release_date}"
                            )
                        }
                    )
                }
            }
        }
    }
}