Jectpack Compose 通过navigation传递 Parcelable 参数

1,014 阅读1分钟

这是实现了Parcelable的数据类

data class UserInfo(val name:String): Parcelable {

    constructor(parcel: Parcel) : this(parcel.readString() ?: "")

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(name)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<UserInfo> {
        override fun createFromParcel(parcel: Parcel): UserInfo {
            return UserInfo(parcel)
        }

        override fun newArray(size: Int): Array<UserInfo?> {
            return arrayOfNulls(size)
        }
    }
}

这里是定义的导航composable

composable(route = "Accounts/{userInfo}", arguments = listOf(
    navArgument("userInfo") {
        // Make argument type safe
        type = NavType.ParcelableType(UserInfo::class.java)
    }
)){
    val name = it.arguments?.getParcelable<UserInfo>("userInfo")?.name
    val account = UserData.getAccount(name)
    SingleAccountBody(account = account)
}

最后发现通过route 无法把Parcelable参数传递过去,因为"Accounts/$userInfo"还是字符串。

 val userInfo = UserInfo("xxx")
 navController.navigate("Accounts/$userInfo")

解决方法: 可以用kotlin的扩展函数

fun NavController.navigate(
    route: String,
    args: Bundle,
    navOptions: NavOptions? = null,
    navigatorExtras: Navigator.Extras? = null
) {
    val routeLink = NavDeepLinkRequest
        .Builder
        .fromUri(NavDestination.createRoute(route).toUri())
        .build()

    val deepLinkMatch = graph.matchDeepLink(routeLink)
    if (deepLinkMatch != null) {
        val destination = deepLinkMatch.destination
        val id = destination.id
        navigate(id, args, navOptions, navigatorExtras)
    } else {
        navigate(route, navOptions, navigatorExtras)
    }
}

导航composable也可以把定义的参数类型去掉

composable(route = "Accounts/Detail"){
    val name = it.arguments?.getParcelable<UserInfo>("userInfo")?.name
    val account = UserData.getAccount(name)
    SingleAccountBody(account = account)
}

导航到对应的composable

navController.navigate("Accounts/Detail",
    Bundle().apply { putParcelable("userInfo", UserInfo(it)) })

这里用的是navigation-compose2.4.1版本的

implementation "androidx.navigation:navigation-compose:2.4.1"

最后感谢:stackoverflow.com/questions/6…