Fragments being inflated with old data, when going back to an activity that was stopped

android, android-activity, android-fragments, android-pageradapter, android-viewpager

Solution

my answer will be better if you'll post the fragment transaction you commit in activity A.

not sure that you know it or not - if Activity A is re-created when it pop back from back stack - it means that it restored from previous instance state.

in that case, you should not perform the transaction again, because - it already happens automatically via the super.onCreate() Activity method. in fact, if you'll perform the fragment trasaction in that case - you'll cause the same fragment to be added twice (2 instances)

you can know if currently `onCreate()` been called from restoring instance state by checking if `savedInstanceState` parameter is null or not.

my assumption is that you are not checking `savedInstanceState`, and performing the transaction anyway.

if I'm right, then the following change should fix the fragment duplication problem:

instead of:

public static class ActivityA extends Activity {

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

        performFragmentTransaction();

}

write:

public static class ActivityA extends Activity {

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

        if (savedInstanceState == null) {
           performFragmentTransaction();
        }
}

more info at - http://developer.android.com/guide/components/fragments.html

Problem

Activity A has fragments. When it starts an intent to activity B, then when `B.finish()`, A executes `onCreate()` again. But this time, even though `A.onCreate()` has a new `PacksPagerAdapter` and a new `ViewPager`, the fragments are shown with old data. I can see that that `onCreateView()` is executed for each fragment, but it still has the old arguments since the `static newInstance()` wasn't called. Arguments are created when FragmentPagerAdapter's `getItem(position)` is called. Here's how it's implemented - ``` public class PackActivity extends Activity { ... PacksPagerAdapter mPacksPagerAdapter; ViewPager mViewPager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mPacksPagerAdapter = new MyPagerAdapter(getFragmentManager()); // Set up the ViewPager with the sections adapter. mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setAdapter(mPacksPagerAdapter); mViewPager.setOffscreenPageLimit(PACK_PAGES - 1); mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { actionBar.setTitle(...); } }); } ... } public class MyPagerAdapter extends FragmentPagerAdapter { ... @Override public Fragment getItem(int position) { // getItem is called to instantiate the fragment for the given page. // Return a PlaceholderFragment (defined as a static inner class // below). return PackFragment.newInstance(myData); } ... } public class PackFragment extends Fragment { ... public static PackFragment newInstance(PackInfo pack) { PackFragment fragment = new PackFragment(); Bundle bdl = new Bundle(2); bdl.putSerializable(EXTRA_PACK, pack); bdl.putInt(EXTRA_PACK_POSITION, pack.packNumber); fragment.setArguments(bdl); return fragment; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View packView = inflater.inflate(R.layout.pack_fragment, container, false); // this has the old argument, since newInstance(...) wasn't called PackInfo pack = (PackInfo) getArguments().getSerializable(EXTRA_PACK); ... return packView; } ... } ``` Any idea why new fragments aren't being instantiated on the 2nd creation of activity A? Update - Activity-Fragments lifecycle The answer is, as Tal said, is that activity is being restored, so old fragments are being reattached instead of creating new ones. After spending a lot of time studying this, I've found that there are typically 3 scenarios for activity-fragments lifecycle. Here are the scenarios, the lifecycle and how to reload fragment's old data: New activity Lifecycle: onCreate() ==> onResume() ==> Fragments are created and attached No need to reload. Restored activity Lifecycle: onCreate() ==> Fragments inflated with old data and reattached ==> onResume() In onResume(), remove all fragments and create new ones, either manually or automatically using an adapter - ``` // Remove all fragments FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); for (int i = BuildConfig.PACK_PAGES - 1; i >= 0; i--) { Fragment f = findFragmentByPosition(i); if (f != null) fragmentTransaction.remove(f); } fragmentTransaction.commit(); // This will force recreation of all fragments viewPager.setAdapter(packsPagerAdapter); ``` Resumed activity Lifecycle: onResume() Same as activity restore, remove old fragments and recreate. Note: Some OS versions always restores activity, even when opening a SettingsActivity for a few seconds, and other (older) versions will always resume.

Original source

Related problems