android - 如何在Android compose中通过Navigation传递对象?

标签 android android-jetpack-compose parcelable jetpack-compose-navigation

我正在使用导航组合,并且我试图将整个对象传递到下一个屏幕,因此我通过 hilt 使用共享的 ViewModel ,并创建了该对象的 mutablestate 变量并希望在下一个屏幕中获取其值。 像这样

var campaign = mutableStateOf<Campaign?>(null)
private set

fun addCampaign(campaign: Campaign){
  this.campaign.value = campaign
}

其中 Campaign 只是一个数据类。

在我的导航屏幕中

 LazyColumn (
        content =
        {
            items(viewModel.campaignListCurrent){ campaign ->
                CampaignItem(
                    image = campaign.brand?.image ?: "",
                    title = campaign.name ,
                    id = campaign.id ,
                    description =campaign.description ,
                    date =campaign.createdAt ) {

                    viewModel.addCampaign(
                        CampaignsViewModel.Campaign(...) // the "campaign" object is used to fill this   
                    )
                    Timber.tag("CampaignObject").v(viewModel.campaign.value.toString())
                    viewModel.changed = true
                    navController.navigate(Screen.CampaignDetailsScreen.route)
                }
            }
        })

当我记录数据时,我可以看到它已成功存储。但在下一个屏幕中,当我从同一个 ViewModel 获取数据时,它是空的。尽管它是一个可变状态并且应该改变它的值并且是可观察的,但我认为我根本没有得到可变状态行为,并且任何对其正确解释的链接将不胜感激。

  val campaign by remember { viewModel.campaign }

    Timber.v("CampaignDetailsScreen2: " + campaign.toString())

有人可以向我解释一下为什么它在这里不起作用,即使我使用了启动效果? 为什么不在这里改变它的值?

最佳答案

我设法通过在 NavGraph 中创建一个 SharedViewModel 实例来解决这个问题,以确保它是两个可组合函数中使用的相同实例。

    @Composable
fun CampaignsScreen(
    navController : NavController,
    viewModel: CampaignsViewModel
) {

...

    @Composable
fun CampaignDetailsScreen(
    navController : NavController,
    viewModel: CampaignsViewModel
) {

在我的 NavGraph 中,我将 ViewModel 作为 HiltViewmodel 在构造函数中传递,并从它传递到两个屏幕

    @Composable
    fun SetUpNavGraph (navController : NavHostController,
                       campaignViewModel: CampaignsViewModel = hiltViewModel()) {
...........
    
                loginNavGraph(navController = navController)
        
                homeNavGraph(navController = navController, campaignsViewModel = campaignViewModel)
            }
        }

在主 NavGraph 中,我传递了参数及其相同的实例

fun NavGraphBuilder.homeNavGraph(
    navController : NavHostController,
    campaignsViewModel: CampaignsViewModel
){

    navigation(startDestination = Screen.HomeScreen.route, route = HOME_GRAPH_ROUTE) {
      ................
        composable(Screen.Campaigns.route){
            CampaignsScreen(navController = navController, viewModel = campaignsViewModel)
        }
        composable(Screen.CampaignDetailsScreen.route){
             CampaignDetailsScreen(navController, viewModel = campaignsViewModel)
        }

    }
}

您可以使用 backstackEntry 和 PreviouseBackStack 来解决此问题,但如果您的对象中有 JSON 对象,则它将不起作用,因为您需要手动序列化和反序列化该对象,并且需要更多的时间和代码来实现相同的目标共享 ViewModel 传递 Parclized 对象的目标。直到 Google Solve 在 Compose Navigation 中传递 Parclized 对象之前,如果您的 paralyzed 对象中没有 JSON 对象,我建议您使用 backStack Entry,如果有,请在两个可组合函数之间使用共享 ViewModel。

关于android - 如何在Android compose中通过Navigation传递对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73599427/

相关文章:

android - 使用网络空间而不是服务器来托管我的应用程序数据。

android - 将 Drawable 绘制为位图

android - 将 Compose 的导航库升级到 Alpha 7 后出现问题

android - 自定义模式类中的 Parcelable 抛出 StackOverflow 错误

android - 处理对 SearchView 图标的点击

使用 Dagger 进行 Android 功能测试

android - 如何在 Compose 中创建循环(无尽)Lazycolumn/LazyRow

android - 将 flutter Painter 转换为 compose

java - 为什么即使我没有实现必要的功能,Parcelable 也能工作?

Android:如何将 Parcelable 对象传递给 Intent 并使用 bundle 的 getParcelable 方法?