Search code examples
androidandroid-fragmentsbottomnavigationview

How to save state of Fragment in a SpaceNavigationView


I've already searched about this and found nothing, which helps me to solve my problem. In my Code I have a SpaceNavigationView (like BottomNavigationView) with five Fragments.

So in Fragment A, I've put a Recyclerview. If an item of the Recyclerview gets clicked, it will replace the current fragment with a new child fragment B.

In Fragment B I've set a Chronometer, which should count the time, when it gets pressed. Now if I switch from Fragment B to Fragment C and go back to Fragment B, the Chronometer starts by zero, because the fragment was replaced.

I've tried to used onSaveInstanceState, so that it can be called when Fragment is recreated, but this doesn't work for me.

Here's a piece of the HomeActivity, which includes all the Fragments.

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

So if i navigate now to FragmentHome and use the OnClickListener for Reycleritems, I will switch to Fragment_Chronograph

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

So now I'm in Fragment_Chronograph and want to save the base for Chronograph. I will save the variable in onSavedInstanceState, which gets called when Activity is Paused.

 @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());
    }

At the end i've put this code for restore in the OnCreate Method:

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

The OnSaveInstanceState gets called, but in the OnCreate Method it won't be called. I would be very thankful if someone could help me with this problem. I'm searching for days and didnt get a solution.


Solution

  • @Arvin

    FragmentHome ist initiated in the init() method;

    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.