You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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字符串传递:

  1. 给HomeInfo添加@Serializable注解:
import kotlinx.serialization.Serializable

@Serializable
data class HomeInfo(
    val id: Int,
    val title: String,
    val description: String
)
  1. 修改路由跳转逻辑:
// 更新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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 06:15:21