Как сохранить состояние фрагмента в SpaceNavigationView

Я уже искал об этом и ничего не нашел, что помогло мне решить мою проблему. В моем коде есть SpaceNavigationView (например, BottomNavigationView) с пятью фрагментами.

Итак, во фрагменте A я поместил Recyclerview. Если щелкнуть элемент Recyclerview, он заменит текущий фрагмент новым дочерним фрагментом B.

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

Я пытался использовать onSaveInstanceState, чтобы его можно было вызвать при воссоздании фрагмента, но у меня это не работает.

Вот часть HomeActivity, которая включает все фрагменты.

  protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);

        init();
        setFragment(fragmentHome);


        navigationView.initWithSaveInstanceState(savedInstanceState);
        navigationView.addSpaceItem(new SpaceItem("", R.drawable.bottom_baby));
        navigationView.addSpaceItem(new SpaceItem("", R.drawable.bottom_advise));
        navigationView.addSpaceItem(new SpaceItem("", R.drawable.ic_favorite_black_24dp));
        navigationView.addSpaceItem(new SpaceItem("", R.drawable.ic_settings));


        navigationView.setSpaceOnClickListener(new SpaceOnClickListener() {
            @Override
            public void onCentreButtonClick() {
                setFragment(fragmentPlayground);
                navigationView.setCentreButtonSelectable(true);
            }

            @Override
            public void onItemClick(int itemIndex, String itemName) {
                switch (itemIndex) {
                    case 0:
                        setFragment(fragmentHome);
                        return;
                    case 1:
                        setFragment(fragmentAdvising);
                        return;
                    case 2:
                        setFragment(fragmentMemories);
                        return;
                    case 3:
                        setFragment(fragmentSettings);
                        return;
                    default:
                        setFragment(fragmentHome);
                        return;

                }
            }

            @Override
            public void onItemReselected(int itemIndex, String itemName) {
                Toast.makeText(HomeActivity.this, itemIndex + " " + itemName, Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void setFragment(Fragment fragment) {
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.container, fragment);
        fragmentTransaction.commit();
    }

Итак, если я перейду сейчас к FragmentHome и использую OnClickListener для Reycleritems, я переключусь на Fragment_Chronograph

 @Override
    public void onItemClick(int position) {
        switch (position) {
            case 0:
                getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment_chronograph).commit();
        }

Итак, теперь я нахожусь в Fragment_Chronograph и хочу сохранить базу для Chronograph. Я сохраню переменную в onSavedInstanceState, которая вызывается, когда действие приостанавливается.

 @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        startTime = SystemClock.elapsedRealtime() - chronometerLeft.getBase();
        outState.putLong(CHRONOLEFT_TIME_SAVE_ID,startTime);
        super.onSaveInstanceState(outState);

    @Override
    public void onPause() {
        super.onPause();
        onSaveInstanceState(new Bundle());
    }

В конце я поместил этот код для восстановления в метод OnCreate:

if (savedInstanceState != null) {
            startTime = savedInstanceState.getLong(CHRONOLEFT_TIME_SAVE_ID,0);
            chronometerLeft.setBase(startTime - SystemClock.elapsedRealtime());
            chronometerLeft.start();

Вызывается OnSaveInstanceState, но в методе OnCreate он не вызывается. Буду очень благодарен, если кто-нибудь поможет мне с этой проблемой. Я ищу несколько дней и не нашел решения.


person Vijay    schedule 11.05.2020    source источник
comment
всем привет . пожалуйста, дайте мне знать setFragment (fragmentHome); где инициируется ваш фрагмент   -  person Arvin Rezaei    schedule 11.05.2020
comment
привет, Арвин, спасибо за ответ. см. мой ответ ниже с кодом.   -  person Vijay    schedule 11.05.2020


Ответы (2)


в методе набора фрагментов сначала найдите фрагмент с идентификатором, а затем проверьте, не является ли он нулевым, замените это

Fragment fragment = getSupportFragmentManager().findFragmentByTag(TAG_PLACEHOLDER);
    if (fragment == null) {
        fragment = new PlaceholderFragment();
    }
    getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.container, fragment, TAG_PLACEHOLDER)
            .commit();

Примечание: вы должны добавить тег к своим фрагментам

person Arvin Rezaei    schedule 11.05.2020

@Arvin

FragmentHome запускается в методе init ();

private void init() {

        navigationView = findViewById(R.id.space);

        fragmentHome = new FragmentHome();
        fragmentAdvising = new FragmentAdvising();
        fragmentMemories = new FragmentMemories();
        fragmentSettings = new FragmentSettings();
        fragmentPlayground = new FragmentPlayground();


============= UPDATE =================


Problem was solved. I didn't have to use OnSavedInstanceState. I used a Helperclass to store the variable of the Chronometerbase. In OnCreate method i check if the variable is not null, then restore the before saved base. 
person Vijay    schedule 11.05.2020