从bottomNavigationView导航到片段B时保存片段A的状态

Posted

技术标签:

【中文标题】从bottomNavigationView导航到片段B时保存片段A的状态【英文标题】:Save state of fragment A when navigating from bottomNavigationView to fragment B 【发布时间】:2020-07-07 13:47:32 【问题描述】:

我是 android 新手,我一直在努力保存片段的状态。 我的应用在底部导航视图中有 5 个选项(我使用的是 Android 的默认活动)。在片段 A(实际上称为“SearchFragment”)中,我有一个按钮,当单击它时,它会在 TextBox 中设置一些文本。我想在导航到另一个片段并返回片段 A 时保存该片段的状态(其中包含文本)。

根据我编写的代码它会在改变方向时保存片段的状态,但在导航到其他片段然后返回时不会这样做。

如何更改代码?或者有没有其他方法可以保存导航片段的当前状态?我真的需要一些帮助...感谢您的关注!

我的 mainActivity 如下所示:

    public class MainActivity extends AppCompatActivity 

        @Override
        protected void onCreate(Bundle savedInstanceState) 
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            BottomNavigationView navView = findViewById(R.id.nav_view);
            // Passing each menu ID as a set of Ids because each
            // menu should be considered as top level destinations.

            AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
                    R.id.navigation_search, R.id.navigation_explore, R.id.navigation_trips, R.id.navigation_groups,R.id.navigation_profile)
                    .build();

            NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
            NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
            NavigationUI.setupWithNavController(navView, navController);
        

    

片段类如下所示:


    public class SearchFragment extends Fragment 

        private SearchViewModel searchViewModel;
        Button b;
        TextView text;
        Bundle savedState = null;

        public View onCreateView(@NonNull LayoutInflater inflater,
                                 ViewGroup container, Bundle savedInstanceState) 

            View root = inflater.inflate(R.layout.fragment_search, container, false);

            searchViewModel = ViewModelProviders.of(this).get(SearchViewModel.class);
            final TextView textView = root.findViewById(R.id.text_dashboard);
            searchViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() 
                @Override
                public void onChanged(@Nullable String s) 
                    textView.setText(s);
                
            );
            Log.i("state","onCreate");
            Log.i("bundleIsNull", "" + (savedState == null));


            b  = root.findViewById(R.id.button2);
            text = root.findViewById(R.id.textView);


            b.setOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View v) 
                    text.setText("YEEEY");
                    Log.i("bundleIsNull", "" + (savedState == null));
                
            );


            if(savedInstanceState != null && savedState == null) 
                savedState = savedInstanceState.getBundle("buttonText");
            
            if(savedState != null) 
                text.setText(savedState.getCharSequence("buttonText"));
            
            savedState = null;

            return root;
        


        @Override
        public void onDestroyView() 
            super.onDestroyView();
            Log.i("state", "onDestroyView");
           savedState = saveState();
           text = null;
           b = null;
        

        private Bundle saveState() 
            Bundle state = new Bundle();
            state.putCharSequence("buttonText", text.getText());
            return state;
        

        @Override
        public void onSaveInstanceState(Bundle outState) 
            super.onSaveInstanceState(outState);
            Log.i("state", "onSaveInstanceState");
            outState.putBundle("buttonText", (savedState != null)? savedState : saveState());
        

        @Override
        public void onPause() 
            super.onPause();
            Log.i("state","onPause");
        
    

【问题讨论】:

查看这个创建自定义导航器的解决方案。 ***.com/a/51684125/10300202 【参考方案1】:

关于带有底部导航栏的 Android 导航组件的一些事实。

-> 片段总是被重新创建(一旦用户导航到另一个片段,就会调用 onCreate、onViewCreated、onViewDestroyed)

-> Fragment 只会在 Activity 重新创建时保存其状态(例如屏幕旋转),在 Fragment 之间导航不会保存 Fragment 的状态。

我想保存这个片段的状态(那里有文字) 导航到另一个片段并返回片段 A (并保留上一次单击按钮后的文本)。

这是不可能的,因为在创建 FragmentA 的新实例时 您从 fragmentB 导航回 Fragment A。

到目前为止,您无法使用导航控制器实现此目的。

由于您使用的是导航组件,您应该切换到使用Viewmodel来解决保留片段状态的问题。

请参阅以下链接,了解如何使用视图模型在 Fragment 之间进行通信和保存数据。

https://androidwave.com/fragment-communication-using-viewmodel/

【讨论】:

感谢您的帮助!!它工作了 :) 我为所有片段添加了一个 sharedViewModel,现在它可以工作了 嘿@Kate 你能分享一下你是如何在 github 上做的吗?谢谢! 有一个视频模型用于此目的,有没有一种方法可以让我们使用 scrollToPositionrecycler view 。由于视图模型保留了最新的拉取数据并且已恢复。我们总是可以将数据附加到适配器,并在更改viewmodel 中的片段更新列表并在恢复时,在适配器中重新发布,但这总是滚动到顶部但不是最后保存的 ui 位置,scrollToPosition 也不起作用。有什么想法吗?

以上是关于从bottomNavigationView导航到片段B时保存片段A的状态的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 material.BottomNavigationView 设置 Jetpack 导航

导航组件 - BottomNavigationView - 返回时不要保留 startDestination 片段

使用导航组件时从 BottomNavigationView 中移除 Badge

Android ------ Android X 的BottomNavigationView底部导航栏

Android ------ Android X 的BottomNavigationView底部导航栏

Android ------ Android X 的BottomNavigationView底部导航栏