![](/img/trans.png)
[英]Jetpack Compose Navigation: Direct navigation to route in a nested graph which is not startDestination
[英]Jetpack Compose Navigation - pass argument to startDestination
我正在構建的應用程序使用帶路線的組合導航。 挑戰在於起始目的地是動態的。
這是一個最小的例子:
class MainActivity : ComponentActivity()
{
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = "dynamic/1", // doesn't work
// startDestination = "static", // workaround
) {
composable(
route = "dynamic/{$ARG_ID}",
arguments = listOf(navArgument(ARG_ID) { type = NavType.StringType }),
) {
val id = it.arguments?.getString(ARG_ID)
Text("dynamic route, received argument: $id!")
}
// part of the workaround
// composable(
// route = "static",
// ) {
// LaunchedEffect(this) {
// navController.navigate("dynamic/1")
// }
// }
}
}
}
companion object
{
const val ARG_ID = "id"
}
}
該應用程序崩潰
java.lang.IllegalArgumentException: navigation destination route/1 is not a direct child of this NavGraph
該問題僅在“動態”路線用作起始目的地時才存在。 這可以通過使用startDestination = "static"
來驗證。
雖然,“靜態”路由解決方法有效,但我正在尋找沒有它的解決方案,因為它有點混淆了代碼,並且還在后台堆棧中創建了一個額外的條目。
-> 重現問題的完整代碼示例
相關問題
編輯:
我想強調的是,原始示例過去不包含“靜態”可組合項。 我只添加了“靜態”可組合項以獲得有效的startDestination
並證明可以導航到“動態”可組合項。
更新:
即使切換到可選 arguments 的查詢參數語法,提供默認值,並設置沒有任何參數的起始目的地也不起作用。
以下變化
NavHost(
navController = navController,
startDestination = "dynamic",
) {
composable(
route = "dynamic?$ARG_ID={$ARG_ID}",
arguments = listOf(navArgument(ARG_ID) { type = NavType.StringType; defaultValue = "1" }),
) {
val id = it.arguments?.getString(ARG_ID)
Text("dynamic route, received argument: $id!")
}
}
導致異常
java.lang.IllegalArgumentException: navigation destination dynamic is not a direct child of this NavGraph
完全歸功於ianhanniballake ,他在評論中向我解釋了解決方案。 我將在這里展示我的代碼示例的工作版本。
對我來說最大的見解是:
startDestination
不能匹配模式匹配意義上的可組合route
,但它必須是完全相同的字符串。
這意味着參數不能直接通過startDestination
設置,而必須通過參數的defaultValue
設置。
這是工作示例:
class MainActivity : ComponentActivity()
{
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
NavHost(
navController = navController,
// 1st change: Set startDestination to the exact string of route
startDestination = "dynamic/{$ARG_ID}", // NOT "dynamic/1", provide arguments via defaultValue
) {
composable(
route = "dynamic/{$ARG_ID}",
// 2nd change: Set startDestination argument via defaultValue
arguments = listOf(navArgument(ARG_ID) { type = NavType.StringType; defaultValue = "1" }),
) {
val id = it.arguments?.getString(ARG_ID)
Text("dynamic route, received argument: $id!")
}
}
}
}
companion object
{
const val ARG_ID = "id"
}
}
該方法同樣適用於以查詢參數形式提供的參數。
老實說,我認為這是一個小限制,因為現在開始路線決定了defaultValue
必須是什么。 我可能想設置一個不同的defaultValue
或根本沒有。 然而,在大多數情況下,這應該是最優雅的解決方案。
不應在“startDestination”NavHost 中使用動態路由值 --> navController.navigate(<dynamic route >)
所有功勞歸功於ianhanniballake和Peter 。 在我的例子中,我沒有在參數數據的路由中添加任何額外的(強制鍵/可選鍵)。 我保持路線清潔,如下所示:
導航圖:
navigation(route = Route.Root.route, startDestination = Route.SubmitForm.route) {
composable(
route = Route.SubmitForm.route,
arguments = listOf(
navArgument(ARG_KEY) {
type = NavType.StringType
defaultValue = JsonConverter.toJson(user, User::class.java)
},
)
)
}
路由封class:
sealed class Route(val route: String) {
object MyRoute : Route("$ROOT/submit-form")
}
在視圖 model 中,只需獲取如下數據:
@HiltViewModel
class MyViewModel @Inject constructor(
stateHandle: SavedStateHandle,
) : ViewModel {
lateinit var user
init {
user = stateHandle.get<String>(ARG_NAME) // Supported data types
}
}
它對我有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.