ViewPager and fragments — what's the right way to store fragment's state?
When the FragmentPagerAdapter
adds a fragment to the FragmentManager, it uses a special tag based on the particular position that the fragment will be placed. FragmentPagerAdapter.getItem(int position)
is only called when a fragment for that position does not exist. After rotating, Android will notice that it already created/saved a fragment for this particular position and so it simply tries to reconnect with it with FragmentManager.findFragmentByTag()
, instead of creating a new one. All of this comes free when using the FragmentPagerAdapter
and is why it is usual to have your fragment initialisation code inside the getItem(int)
method.
Even if we were not using a FragmentPagerAdapter
, it is not a good idea to create a new fragment every single time in Activity.onCreate(Bundle)
. As you have noticed, when a fragment is added to the FragmentManager, it will be recreated for you after rotating and there is no need to add it again. Doing so is a common cause of errors when working with fragments.
A usual approach when working with fragments is this:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
CustomFragment fragment;
if (savedInstanceState != null) {
fragment = (CustomFragment) getSupportFragmentManager().findFragmentByTag("customtag");
} else {
fragment = new CustomFragment();
getSupportFragmentManager().beginTransaction().add(R.id.container, fragment, "customtag").commit();
}
...
}
When using a FragmentPagerAdapter
, we relinquish fragment management to the adapter, and do not have to perform the above steps. By default, it will only preload one Fragment in front and behind the current position (although it does not destroy them unless you are using FragmentStatePagerAdapter
). This is controlled by ViewPager.setOffscreenPageLimit(int). Because of this, directly calling methods on the fragments outside of the adapter is not guaranteed to be valid, because they may not even be alive.
To cut a long story short, your solution to use putFragment
to be able to get a reference afterwards is not so crazy, and not so unlike the normal way to use fragments anyway (above). It is difficult to obtain a reference otherwise because the fragment is added by the adapter, and not you personally. Just make sure that the offscreenPageLimit
is high enough to load your desired fragments at all times, since you rely on it being present. This bypasses lazy loading capabilities of the ViewPager, but seems to be what you desire for your application.
Another approach is to override FragmentPageAdapter.instantiateItem(View, int)
and save a reference to the fragment returned from the super call before returning it (it has the logic to find the fragment, if already present).
For a fuller picture, have a look at some of the source of FragmentPagerAdapter (short) and ViewPager (long).
Saving and restoring fragment state in viewpager
Use mViewPager.setOffscreenPageLimit(noOfPageYouWantToKeepInMemory);
Where to restore fragment state that is inside ViewPager
So I found where the problem was. Just posting the answer here. So when the screen is rotated, although I am updating the data source, I have not reattached the listview with the updated adapter. So I just did that and it works.
if(savedInstanceState!=null) {
Log.v("---------------->","restored!");
nowDataList = savedInstanceState.getParcelableArrayList("savedNowDataList");
nowForecastAdapter = new NowForecastAdapter(this, nowDataList);
lvNowList.setAdapter(nowForecastAdapter);
nowForecastAdapter.notifyDataSetChanged();
}
Just posted the answer if anyone made the same mistake and was wondering what went wrong.
Save state of viewpager fragment in navigation drawer fragments
Have 3 fragments and swipe to 3rd fragment then back to 1st fragment, the 1st fragment's data is gone?
Related Topics
Save Arraylist to Sharedpreferences
How to Stop Edittext from Gaining Focus When an Activity Starts in Android
How to Convert a Drawable to a Bitmap
How to Determine When Fragment Becomes Visible in Viewpager
Difference Between "@Id/" and "@+Id/" in Android
How to Update Gradle in Android Studio
How to Remove All Debug Logging Calls Before Building the Release Version of an Android App
Make an Http Request With Android
Android List View Inside a Scroll View
How to Pick an Image from Gallery (Sd Card) For My App
Sending Data Back to the Main Activity in Android
How to Run a Runnable Thread in Android At Defined Intervals
How to Support Arabic Text in Android
Android: How to Prevent the Soft Keyboard from Pushing My View Up