Сохранение состояния фрагмента A при переходе от bottomNavigationView к фрагменту B

Я новичок в Android, и я уже некоторое время борюсь с сохранением состояния фрагмента. В моем приложении есть 5 опций в нижней панели навигации (я использую активность по умолчанию для Android). Во фрагменте A (фактически называемом «SearchFragment») у меня есть кнопка, и при нажатии на нее устанавливается некоторый текст в TextBox. Я хочу сохранить состояние этого фрагмента (с текстом там) при переходе к другому фрагменту и возвращении к фрагменту A (и оставить текст после предыдущего нажатия кнопки).

Из кода, который я написал, он сохраняет состояние фрагмента, например, при изменении ориентации, но не делает этого при переходе к другим фрагментам и последующем возвращении.

Как я мог изменить код? Или есть другой способ сохранить текущее состояние фрагмента при навигации? Мне действительно нужна помощь здесь... и спасибо за внимание!

Моя основная активность выглядит так:

    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");
        }
    }


comment
см. это решение, создающее собственный навигатор. stackoverflow.com/a/51684125/10300202   -  person Javid Sattar    schedule 28.09.2020


Ответы (1)


Несколько фактов о компоненте навигации Android с нижней панелью навигации.

-> Фрагменты всегда создаются заново (onCreate, onViewCreated, onViewDestroyed вызываются, как только пользователь переходит к другому фрагменту)

-> Фрагмент сохранит свое состояние только при воссоздании действия (например, при повороте экрана), переход между фрагментами не сохраняет состояние фрагмента.

Я хочу сохранить состояние этого фрагмента (с текстом там) при переходе к другому фрагменту и возвращении к фрагменту A (и оставить текст после предыдущего нажатия кнопки).

Это невозможно, так как новый экземпляр FragmentA создается при переходе от фрагмента B к фрагменту A.

вы не можете добиться этого с помощью навигационного контроллера на данный момент.

Поскольку вы используете компонент навигации, вам следует переключиться на использование Viewmodel, чтобы решить проблему сохранения состояния фрагмента.

Проконсультируйтесь по следующей ссылке, чтобы узнать, как обмениваться данными и сохранять данные между фрагментами с помощью модели представления.

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

person Usman Zafer    schedule 26.03.2020
comment
Спасибо за помощь !! Это сработало :) Я добавил sharedViewModel для всех фрагментов, и теперь это работает. - person Kate; 27.03.2020
comment
Рад, что смог помочь :) - person Usman Zafer; 27.03.2020
comment
Эй, @Kate, не могли бы вы поделиться, как вы это сделали, на github или что-то в этом роде? Благодарю вас! - person Abhishek AN; 10.04.2021
comment
с видеомоделью, используемой для этой цели, есть ли способ, которым мы можем сделать scrollToPosition с recycler view . Поскольку модель представления хранит последние извлеченные данные, которые восстанавливаются. Мы всегда можем добавить данные в адаптер и при изменении списка обновлений фрагментов в viewmodel и при восстановлении опубликовать обратно в адаптере, но это всегда прокручивается вверх, но не на последнюю сохраненную позицию пользовательского интерфейса, и scrollToPosition тоже не будет работать. Любые идеи ? - person 89n3ur0n; 06.06.2021