名词解释
什么是正向反向参数传递呢
正向:相当于一个Activity
启动另一个Activity
并向其传递参数; 反向:相当于一个Activity
退出的时候向启动它的Activity
回传参数;
使用SaveStateHandle实现
下面的代码是官方推荐的方法
向上级页面返回数据
/** * 返回指定的route并回调参数 */ fun NavHostController.goBackRouteWithParams1( route: String, autoPop: Boolean = true, callback: (SavedStateHandle.() -> Unit)? = null, ) { val entry = getBackStackEntry(route) entry.savedStateHandle?.let { callback?.invoke(it) } if (autoPop) { popBackStack() } } /** * 回到上级页面,并回调参数 */ fun NavHostController.goBackWithParams1( autoPop: Boolean = true, callback: (SavedStateHandle.() -> Unit)? = null, ) { // if (previousBackStackEntry?.arguments == null){ // previousBackStackEntry?.arguments = Bundle() // } previousBackStackEntry?.savedStateHandle?.let { callback?.invoke(it) } if (autoPop) { popBackStack() } } 复制代码
接收数据代码
val saveStateHandle = controller.currentBackStackEntryAsState().value?.savedStateHandle saveStateHandle?.get<String>("data")//获取指定key对应的数据 复制代码
思路(此方法不是最佳答案,已经被证实不是官方推荐的方案,不看也罢)
本文主要讲反向参数传递,正向参数传递参考:正向参数传递
起先关于这个问题是没什么思路的,网上(包括google官网)也没有相关说明,以至于公司新开的项目,虽然使用compose
来写的,但是反向参数传递却是自定义的一个总线框架来做的。
使用总线框架做明显是不合适的。
~~基于这样一个原因,项目完成后我决定研究一下这个问题。~~~~
我们都知道compose的页面打开关闭是使用NavHostController
来进行的,那么有理由相信,如果有反向数据传递的方法必然也与NavHostController
来处理。
后面的做法也简单,将所有的NavHostController
中方法过一遍基本就能过滤出可能的几个。
~~通过过滤有几个方法被选中:findDestination
、getBackStackEntry
、previousBackStackEntry
、controller.currentBackStackEntryAsState()
。~~~~
最终有效的方法刚好就是:getBackStackEntry
、previousBackStackEntry
,通过这两个方法可以获取NavBackStackEntity
,而NavBackStackEntity
中有arguments:Bundle
参数,通过arguments参数就可以进行数据传递。
在上级页面使用controller.currentBackStackEntryAsState()
可以获取到Bundle
从而拿到返回的参数。
代码
方法封装
我将回传参数的代码进行封装如下
**方法2:** `goBackWithParams` 直接返回上级页面,并回传参数 ```kt /** * 返回指定的route并回调参数 */ fun NavHostController.goBackRouteWithParams( route: String, autoPop: Boolean = true, callback: (Bundle.() -> Unit)? = null, ) { getBackStackEntry(route).arguments?.let { callback?.invoke(it) } if (autoPop) { popBackStack() } } /** * 回到上级页面,并回调参数 */ fun NavHostController.goBackWithParams( autoPop: Boolean = true, callback: (Bundle.() -> Unit)? = null, ) { previousBackStackEntry?.arguments?.let { callback?.invoke(it) } if (autoPop) { popBackStack() } } ``` ### 业务代码 ```kt @Composable fun NavigateParams1View(controller: NavHostController) { val bundle = controller.currentBackStackEntryAsState().value Column(Modifier .fillMaxSize() .background(Color.Red), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally) { Text(text = "展示下一级页面返回来的数据", style = TextStyle(fontSize = 20.sp)) Box(Modifier .padding(horizontal = 14.dp, vertical = 20.dp) .size(120.dp) .background(color = Color.Gray, RoundedCornerShape(10.dp)), contentAlignment = Alignment.Center ) { Text(text = bundle?.arguments?.getString("data") ?: "未返回数据") } Button(onClick = { controller.navigate(navigate_param_transfer2) }, modifier = Modifier.padding(top = 20.dp)) { Text(text = "点击跳转到下一级页面") } } } @Composable fun NavigateParams2View(controller: NavHostController) { Column(Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally) { Text(text = "展示下一级页面返回来的数据") Button(onClick = { controller.goBackRouteWithParams(navigate_param_transfer1) { putString("data", "Hello world to you") } },modifier = Modifier.padding(top = 20.dp)) { Text(text = "点击跳转到下一级页面") } Button(onClick = { controller.goBackWithParams { putString("data", "Hello world to you") } },modifier = Modifier.padding(top = 20.dp)) { Text(text = "点击跳转到下一级页面") } } } ``` ## 实现效果 ![两种方法实现反向参数传递](https://files.mdnice.com/user/15648/ee2c266e-9ace-452b-aa50-9c122ec5ea27.gif) git: https://github.com/ananananzhuo-blog/ComposeNavigate