通过导航组件在底部导航片段之间传递数据

Posted

技术标签:

【中文标题】通过导航组件在底部导航片段之间传递数据【英文标题】:Passing Data between BottomNavigation fragments via NavigationComponent 【发布时间】:2020-04-19 17:40:41 【问题描述】:

是否可以通过 NavigationContoller 在 BottomNavigation 控制的 Fragment 之间传递 Parcelable 对象/参数?

这是我的应用程序的流程,用户登录到应用程序并打开一个包含底部导航的片段。我能够获得第一个片段的参数(第一个片段使用 NavHostFragment.findNavController(this).navigate(action) 打开)我能够向此操作添加参数并传递值,但 BottomNavigation 没有任何导航指令导航是通过 menuID 完成的。我如何通过捆绑在所有这些底部导航片段之间传递登录用户参数。

我尝试使用 onDestinationChanged() 传递参数

@Override
public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) 
        NavArgument argument = new NavArgument.Builder().setDefaultValue(selectedUser).build();
        destination.addArgument("user", argument);

但应用程序仍会因java.lang.IllegalArgumentException: Required argument "user" is missing and does not have an android:defaultValue 而崩溃

【问题讨论】:

【参考方案1】:
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) 
    super.onViewCreated(view, savedInstanceState);
    
    navController = Navigation.findNavController(getActivity(), R.id.navBottomNavigation);
    NavigationUI.setupWithNavController(R.id.bottomNavigationView, navController);
    NavGraph navGraph = navController.getNavInflater().inflate(R.navigation.nav_sub_graph);

    NavArgument argument = new NavArgument.Builder().setDefaultValue(yourObject).build();
    navGraph.addArgument("yourObject",argument);

    navController.setGraph(navGraph);

在底部导航中传递对象嵌套片段

 navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() 
        @Override
        public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) 

            switch (destination.getId()) 
                case R.id.profileFragment:
                    NavArgument argumentProfile = new NavArgument.Builder().setDefaultValue(yourObject).build();
                    destination.addArgument("yourObject",argumentProfile);

                case R.id.homeFragment:
                    NavArgument argumentHome = new NavArgument.Builder().setDefaultValue(yourObject).build();
                    destination.addArgument("yourObject",argumentHome);

                case R.id.orderFragment:
                    NavArgument argumentOrder = new NavArgument.Builder().setDefaultValue(yourObject).build();
                    destination.addArgument("yourObject",argumentOrder);
            
        
    );

【讨论】:

【参考方案2】:

我们可以像 asad 提到的那样使用 SharedViewModel,也可以使用 NavGraph 来设置参数

navController.getGraph().findNode(R.id.todoFragment)
            .addArgument("user", new NavArgument.Builder()
                    .setDefaultValue(user)
                    .build());

【讨论】:

【参考方案3】:

您也可以在导航文档中使用SharedViewModel Pass data between destinations 他们参考

一般来说,您应该强烈希望只传递最少的数量 目的地之间的数据。例如,您应该将密钥传递给 检索对象而不是传递对象本身,作为总数 所有保存状态的空间在 Android 上是有限的。如果需要通过 大量数据,请考虑使用 ViewModel,如 在片段之间共享数据。

【讨论】:

感谢 asad,用户参数只是一个整数值,SharedViewModel 是在所有 BottomNavigated 片段之间共享此用户 ID 的唯一选项吗? 您只能根据文档Pass data to the start destination 将数据传递到起始目的地,如果您使用onDestinationChanged,则第一次无法获取参数

以上是关于通过导航组件在底部导航片段之间传递数据的主要内容,如果未能解决你的问题,请参考以下文章

使用导航从工具栏菜单项单击在片段之间传递数据 - Kotlin

通过片段之间的导航传递数据android studio

如何使用底部导航视图和 Android 导航组件将参数传递给片段?

如何在两个片段之间传递位图? (我正在使用 Android 导航组件)

如何在导航抽屉中的两个片段之间传递数据

将数据从底部工作表对话框片段传递到片段