Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fragment not added (inconsistent crash)

In my MainActivity, I have:

@Override
protected void onResume() {
    super.onResume();

    checkForCrashes();
    checkForTutorial();
    checkForUpdates();
    setStore();
    setup();
}

In setup(), I call initializeTabs() in a callback:

protected void setup() {
    final Store s = getStore();
    setBackground();

    if (s == null) {
        unauthorizedHandler();
        return;
    }
    final Context mainActivity = this;
    fragments = getTabFragments();

    StoresController.getStoreDetails(s, mainActivity, new Callback<StoreDetailDecorator>() {
        @Override
        public void success(StoreDetailDecorator storeDetailDecorator, Response response) {
            s.prettyName = storeDetailDecorator.store.pretty_name;
            s.save();
            Log.v(TAG, s.prettyName);
            TextView toolbar_label = (TextView)findViewById(R.id.toolbar_label);
            toolbar_label.setText(MainActivity.getTruncatedMenuName(s.name()));

            SummaryTab t1 = (SummaryTab)fragments.get(0);
            t1.notifier = (SummaryTabLoadingNotifier)mainActivity;
            initializeTabs(s, fragments);
            t1.populateReport();
        }
    }
}

public void initializeTabs(Store s, List<Fragment> fragments ) {
    ViewPagerAdapter adapter =  new ViewPagerAdapter(getSupportFragmentManager(), getTabTitles(), fragments);
    ViewPager pager = (ViewPager) findViewById(R.id.pager);
    pager.setOffscreenPageLimit(2);
    pager.setAdapter(adapter);
}

That last line is crashing for some customers.

java.lang.IllegalStateException: Fragment InfoTab{1bcb80f} is not currently in the FragmentManager

But not every time. Why would this happen sometimes? Something to do with the fragment not being connected? I read some things about checking isAdded() on a fragment, but that's for checking if a fragment is added to an Activity. I'm using a FragmentStatePagerAdapter :

public class ViewPagerAdapter extends FragmentStatePagerAdapter {
    private CharSequence[] titles;
    private List<Fragment> fragmentList = new ArrayList<>();

    public ViewPagerAdapter(FragmentManager fragmentManager, CharSequence titles[], List<Fragment> fragmentList) {
        super(fragmentManager);
        this.titles = titles;
        this.fragmentList = fragmentList;
    }

    @Override
    public android.support.v4.app.Fragment getItem(int position) {
        return fragmentList.get(position);
    }

    @Override
    public CharSequence getPageTitle(int position) { return titles[position]; }

    @Override
    public int getCount() { return fragmentList.size(); }

    @Override
    public Parcelable saveState() {
        return null;
    }
}

Could saveState(){ return null;} be it? This is there, as I understand things, to ensure the view is refreshed every time.

like image 450
quantumpotato Avatar asked Feb 12 '17 20:02

quantumpotato


2 Answers

onResume() is called every time your activity returns to foreground.

If one of your users, for example, presses the home button and returns to your app then getStoreDetails() will be called again and you'll create a new adapter (with the same old fragment list) when the result arrives.

You should instantiate your fragments, create an adapter and populate your viewpager with the adapter only once (onCreate() would be the spot).

When new data arrives from getStoreDetails() just update the already added fragments with the new data.

like image 130
Hanan Rofe Haim Avatar answered Nov 01 '22 08:11

Hanan Rofe Haim


This is because you are returning null in saveState(). You shouldn't try to override this behavior. But even if you want to do it for some reason, you have to override public void restoreState(Parcelable state, ClassLoader loader) as well to avoid crash, because that method is relying on data saved in saveState().

But I would suggest you to not override it at all, and instead explain what you wanted to achieve there.

like image 20
Dimezis Avatar answered Nov 01 '22 10:11

Dimezis