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.