ncapdevi / FragNav

An Android library for managing multiple stacks of fragments
1.5k stars 220 forks source link

Current Fragment isn't re-created on configuration change #220

Closed techyourchance closed 5 years ago

techyourchance commented 5 years ago

First of all - great library. Very nice API and functionality. Said that, we ran into an issue and two developers have already spent hours trying to resolve it, but without much success.

Problem: upon configuration change, the currently shown Fragment is destroyed and detached, but isn't re-created after the Activity is re-created (neither of lifecycle methods of that Fragment are called).

What we tried: we tested the behavior of BottomTabsActivity in the sample app and saw that it works as expected (unlike our app). Then we basically wrote the same code in our app (translated to Java). To our great surprise, this didn't resolve the issue.

Our current code (stripped down to just the relevant parts):

public class MainActivity extends BaseActivity implements
        MainViewMvc.Listener,
        FragNavController.RootFragmentListener,
        FragNavController.TransactionListener {

    private static final String TAG = "MainActivity";

    private FragNavController mFragNavController;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        super.setContentView(R.layout.activity_main);

        mFragNavController = new FragNavController(getSupportFragmentManager(), R.id.frame_content);

        mFragNavController.setTransactionListener(this);
        mFragNavController.setRootFragmentListener(this);
        mFragNavController.setCreateEager(true);
        mFragNavController.setFragNavLogger((s, throwable) -> Log.e(TAG, s, throwable));
        mFragNavController.setDefaultTransactionOptions(new FragNavTransactionOptions.Builder().build());
        mFragNavController.setFragmentHideStrategy(FragNavController.DETACH_ON_NAVIGATE_HIDE_ON_SWITCH);
        mFragNavController.initialize(INDEX_COLLECTIONS, savedInstanceState);

        if (savedInstanceState == null) {
            navigateToTab(BottomTabs.TEMPLATES);
        }

    }

    @Override
    public void onSaveInstanceState(Bundle saveInstanceState) {
        mFragNavController.onSaveInstanceState(saveInstanceState);
    }

    @Override
    public int getNumberOfRootFragments() {
        return 3;
    }

    @NotNull
    @Override
    public Fragment getRootFragment(int index) {
        switch (index) {
            case INDEX_COLLECTIONS:
                return CollectionsFragment.newInstance();
            case INDEX_FAVORITES:
                return FavoritesFragment.newInstance();
            case INDEX_HISTORY:
                return HistoryFragment.newInstance();
        }
        throw new IllegalStateException("Invalid fragment index: " + index);

    }

    private void navigateToTab(BottomTabs tab) {
        switch (tab) {
            case TEMPLATES:
                mFragNavController.switchTab(INDEX_COLLECTIONS);
                break;
            case FAVORITES:
                mFragNavController.switchTab(INDEX_FAVORITES);
                break;
            case HISTORY:
                mFragNavController.switchTab(INDEX_HISTORY);
                break;
        }
    }

    @Override
    public void onFragmentTransaction(@org.jetbrains.annotations.Nullable Fragment fragment, FragNavController.@NotNull TransactionType transactionType) {

    }

    @Override
    public void onTabTransaction(@org.jetbrains.annotations.Nullable Fragment fragment, int i) {

    }
}

As I wrote above, when I start the app, I see "collections" screen. If I then rotate the device, the Activity is re-created, but the space devoted to "content" Fragment remains blank and I see that neither of Fragment's lifecycle methods get called. The behavior of the BottomTabsActivity in the sample app is different (it works as expected), but we just can't understand what we did differently.

We spent hours trying to eliminate many various factors one-by-one, but couldn't find the problem. Help will be greatly appreciated.

solareye commented 5 years ago

@Override public void onSaveInstanceState(Bundle saveInstanceState) { mFragNavController.onSaveInstanceState(saveInstanceState); }

Where is your super.onSaveInstanceState(saveInstanceState) calling?

techyourchance commented 5 years ago

Yes, it was the lack of super.onSaveInstanceState(saveInstanceState). What an embarassment! Thanks for helping @solareye!