Jetpack Compose导航:点击卡片跳转详情页并传递数据的实现
解决Jetpack Compose导航中传递HomeInfo数据到详情页的问题
你之前的Companion Object错误原因
- Companion Object是Kotlin类的伴生对象,必须定义在类内部,不能直接放在文件顶层或Composable函数中,这就是你报错的核心原因。
- 另外,多Activity+Intent的导航方式在Jetpack Compose的单Activity架构下并不推荐,官方更建议使用Navigation Compose来实现页面导航和参数传递。
正确实现步骤(基于Navigation Compose)
1. 添加必要依赖
在你的app/build.gradle.kts(或build.gradle)中添加以下依赖:
dependencies { // Navigation Compose核心库 implementation("androidx.navigation:navigation-compose:2.7.7") // Parcelize支持(用于对象序列化传递) implementation("org.jetbrains.kotlinx:kotlinx-parcelize-runtime:1.0.1") }
2. 让HomeInfo数据类支持序列化
推荐使用Parcelable(性能更优),给你的数据类添加@Parcelize注解并实现Parcelable接口:
import android.os.Parcelable import kotlinx.parcelize.Parcelize @Parcelize data class HomeInfo( val id: Int, val title: String, val description: String, // 你的其他业务字段 ) : Parcelable
3. 定义导航路由
创建密封类统一管理所有页面路由:
sealed class Screen(val route: String) { object Home : Screen("home_screen") object Detail : Screen("detail_screen") }
4. 配置导航宿主(NavHost)
在主入口Composable(比如MainActivity的setContent)中配置导航框架:
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.navigation.NavController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController @Composable fun MainApp() { val navController = rememberNavController() Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { NavHost( navController = navController, startDestination = Screen.Home.route ) { // 首页路由 composable(Screen.Home.route) { HomeScreen(navController = navController) } // 详情页路由,处理参数接收 composable(Screen.Detail.route) { backStackEntry -> val homeInfo = backStackEntry.arguments?.getParcelable<HomeInfo>("home_info") homeInfo?.let { DetailScreen(homeInfo = it) } ?: run { // 参数为空时返回首页 navController.popBackStack() } } } } }
5. HomeScreen中实现卡片点击跳转
在LazyHorizontalGrid的卡片点击事件中,通过navController传递目标数据:
import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid import androidx.compose.foundation.lazy.grid.items import androidx.compose.material3.Card import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.navigation.NavController @Composable fun HomeScreen(navController: NavController) { LazyHorizontalGrid(rows = GridCells.Fixed(2)) { items(HomeInfoModel.homeList) { homeInfo -> Card( modifier = Modifier .padding(8.dp) .clickable { // 跳转到详情页并传递HomeInfo参数 navController.navigate(Screen.Detail.route) { arguments = android.os.Bundle().apply { putParcelable("home_info", homeInfo) } } } ) { // 卡片内容示例 Text( text = homeInfo.title, modifier = Modifier.padding(16.dp) ) } } } }
6. DetailScreen接收并展示数据
直接接收传递过来的HomeInfo对象,渲染详情内容:
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.material3.MaterialTheme @Composable fun DetailScreen(homeInfo: HomeInfo) { Column(modifier = Modifier.padding(16.dp)) { Text( text = homeInfo.title, style = MaterialTheme.typography.headlineMedium, modifier = Modifier.padding(bottom = 8.dp) ) Text( text = homeInfo.description, style = MaterialTheme.typography.bodyLarge ) // 渲染其他业务字段... } }
可选方案:用JSON序列化传递对象
如果你不想依赖Parcelable,可以用kotlinx.serialization将对象转成JSON字符串传递:
- 给
HomeInfo添加@Serializable注解:
import kotlinx.serialization.Serializable @Serializable data class HomeInfo( val id: Int, val title: String, val description: String )
- 修改路由跳转逻辑:
// 更新Screen密封类的详情页路由 object Detail : Screen("detail_screen?home_info={home_info}") { fun createRoute(homeInfo: HomeInfo): String { val json = kotlinx.serialization.json.Json.encodeToString(homeInfo) return "detail_screen?home_info=${android.net.Uri.encode(json)}" } } // HomeScreen中跳转 navController.navigate(Screen.Detail.createRoute(homeInfo)) // NavHost中解析参数 composable(Screen.Detail.route) { backStackEntry -> val homeInfoJson = backStackEntry.arguments?.getString("home_info") val homeInfo = homeInfoJson?.let { kotlinx.serialization.json.Json.decodeFromString<HomeInfo>(android.net.Uri.decode(it)) } homeInfo?.let { DetailScreen(homeInfo = it) } ?: navController.popBackStack() }
内容的提问来源于stack exchange,提问作者Edwin
相关产品推荐
相关产品推荐

