compose 页面间参数正向反向传递方法

简介: compose 页面间参数正向反向传递方法

名词解释


什么是正向反向参数传递呢

正向:相当于一个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中方法过一遍基本就能过滤出可能的几个。

~~通过过滤有几个方法被选中:findDestinationgetBackStackEntrypreviousBackStackEntrycontroller.currentBackStackEntryAsState()。~~~~

最终有效的方法刚好就是:getBackStackEntrypreviousBackStackEntry,通过这两个方法可以获取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



相关文章
|
11天前
|
Python
路由系统中的 path 函数有哪些可选参数?
路由系统中的 path 函数有哪些可选参数?
26 7
|
4月前
|
监控 Serverless 算法框架/工具
函数计算操作报错合集之选中图中部分后报错,但去掉后可以正常请求,是什么原因
在使用函数计算服务(如阿里云函数计算)时,用户可能会遇到多种错误场景。以下是一些常见的操作报错及其可能的原因和解决方法,包括但不限于:1. 函数部署失败、2. 函数执行超时、3. 资源不足错误、4. 权限与访问错误、5. 依赖问题、6. 网络配置错误、7. 触发器配置错误、8. 日志与监控问题。
|
5月前
|
网络协议 Linux 网络安全
Iptables深度解析:四表五链与动作参数
Iptables深度解析:四表五链与动作参数
478 0
|
PyTorch 算法框架/工具
如何将网络参数初始化,或者如何将网络参数还原成原始参数状态
在以上代码中,_initialize_weights()方法用于对网络参数进行初始化。其中,init.ones_表示将权重初始化为1,init.zeros_表示将偏置初始化为0。 3. 如果想将网络参数恢复到初始状态,则可以重新调用_initialize_weights()方法
314 0
lodash反向检索对象的属性和对应的值
lodash反向检索对象的属性和对应的值
82 0
|
JavaScript 前端开发 API
在请求中传入不定长参数实现不同的逻辑处理的解决办法
在请求中传入不定长参数实现不同的逻辑处理的解决办法
|
存储 小程序 Android开发
技术干货 | 轻松两步完成向 mPaaS 小程序传递启动参数
以传递 name 和 pwd 参数为例,分别介绍此场景在 Android 小程序和 iOS 小程序中的实现过程。
9140 0
技术干货 | 轻松两步完成向 mPaaS 小程序传递启动参数
|
PHP
如何计算PHP函数中传递的参数数量
在开始本文之前不知道大家对PHP函数有多少了解,那如果你还是刚入门的新人我就推荐大家先看看PHP自学手册中的《PHP函数》章节,毕竟有句话说的好PHP的真正威力源自于它的函数~ 那么本文将给大家介绍关于函数的基础知识:计算PHP函数中传递的参数数量。 首先给大家简单介绍怎么创建函数:
192 0