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



相关文章
|
XML 前端开发 IDE
在 Compose 中使用 Jetpack 组件库
在 Compose 中使用 Jetpack 组件库
1390 0
|
Android开发
android Compose中沉浸式设计、导航栏、状态栏的处理
android Compose中沉浸式设计、导航栏、状态栏的处理
3194 0
android Compose中沉浸式设计、导航栏、状态栏的处理
|
人工智能 自然语言处理 JavaScript
宜搭上新,DeepSeek 插件来了!
钉钉宜搭近日上线了DeepSeek插件,无需编写复杂代码,普通用户也能轻松调用强大的AI大模型能力。安装后,平台新增「AI生成」组件,支持创意内容生成、JS代码编译、工作汇报等场景,大幅提升工作效率。快来体验这一高效智能的办公方式吧!
3084 9
|
Android开发
AS错误:Duplicate class kotlin.xxx.jdk8.DurationConversionsJDK8Kt found in modules kotlin-stdlib-1.8.22
本文描述了Android Studio中遇到的"Duplicate class found in modules"错误的解决方法,通过在`app/build.gradle`文件中使用`constraints`来排除过时的kotlin-stdlib-jdk7和kotlin-stdlib-jdk8依赖,解决了依赖冲突问题。
1601 1
|
前端开发 API 网络架构
深入浅出:GraphQL 的优势与使用场景
【10月更文挑战第6天】深入浅出:GraphQL 的优势与使用场景
1548 0
|
XML 前端开发 Android开发
Kotlin教程笔记(80) - MVVM架构设计
Kotlin教程笔记(80) - MVVM架构设计
|
JavaScript Java Android开发
kotlin安卓在Jetpack Compose 框架下跨组件通讯EventBus
**EventBus** 是一个Android事件总线库,简化组件间通信。要使用它,首先在Gradle中添加依赖`implementation &#39;org.greenrobot:eventbus:3.3.1&#39;`。然后,可选地定义事件类如`MessageEvent`。在活动或Fragment的`onCreate`中注册订阅者,在`onDestroy`中反注册。通过`@Subscribe`注解方法处理事件,如`onMessageEvent`。发送事件使用`EventBus.getDefault().post()`。
|
JSON 调度 数据库
Android面试之5个Kotlin深度面试题:协程、密封类和高阶函数
本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点。文章详细解析了Kotlin中的协程、扩展函数、高阶函数、密封类及`inline`和`reified`关键字在Android开发中的应用,帮助读者更好地理解和使用这些特性。
589 1
|
安全 网络安全 API
kotlin安卓开发JetPack Compose 如何使用webview 打开网页时给webview注入cookie
在Jetpack Compose中使用WebView需借助AndroidView。要注入Cookie,首先在`build.gradle`添加WebView依赖,如`androidx.webkit:webkit:1.4.0`。接着创建自定义`ComposableWebView`,通过`CookieManager`设置接受第三方Cookie并注入Cookie字符串。最后在Compose界面使用这个自定义组件加载URL。注意Android 9及以上版本可能需要在网络安全配置中允许第三方Cookie。
|
算法 安全 数据安全/隐私保护
Android经典实战之常见的移动端加密算法和用kotlin进行AES-256加密和解密
本文介绍了移动端开发中常用的数据加密算法,包括对称加密(如 AES 和 DES)、非对称加密(如 RSA)、散列算法(如 SHA-256 和 MD5)及消息认证码(如 HMAC)。重点讲解了如何使用 Kotlin 实现 AES-256 的加密和解密,并提供了详细的代码示例。通过生成密钥、加密和解密数据等步骤,展示了如何在 Kotlin 项目中实现数据的安全加密。
1252 1