Where to restore fragment state that is inside ViewPager
Asked Answered
H

2

6

Short Version:

I have an Activity that has a ViewPager. The ViewPager has three fragments inside it. I am storing the data inside the fragments by implementing Parcelable and storing it inside the bundle.

Now the question is where do I restore the data. I am confused because (from what I know) the ViewPager is creating a new instance of the fragment each time I rotate the screen. (A new activity is created -> new ViewPager -> new Fragment). Please do correct me if I am wrong.

Long version:

My ViewPager inside MainActivity

ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(new ForecastFragmentPageAdapter(getSupportFragmentManager(),
            ForecastActivity.this));
viewPager.setOffscreenPageLimit(2);

My FragmentPagerAdapter

 @Override
public Fragment getItem(int position) {
    if (position == 0) {
        return new NowForecastFragment();
    } else if (position == 1) {
        return new HourlyForecastFragment();
    } else {
        return new DailyForecastFragment();
    }
}

Saving state in one of my fragments

    public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    // save data source
    if (nowDataList != null) {
        outState.putParcelableArrayList("savedNowDataList", nowDataList);
    }
}

Thanks in advance!

UPDATE:

According to other solutions posted to similar problems, I also added setRetainInstance(true); in the onCreateView of my fragment. And this is how I am saving and restoring state:

    @Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    // save data source
    if (nowDataList != null) {
        Log.v("---------------->","saved!");
        outState.putParcelableArrayList("savedNowDataList", nowDataList);
    }
}

and restoring in onCreateView

 if(savedInstanceState!=null) {
            Log.v("---------------->","restored!");
            nowDataList = savedInstanceState.getParcelableArrayList("savedNowDataList");
            nowForecastAdapter.notifyDataSetChanged();
        }

I see both the logs being triggered. Why is the data not being restored?

Heteronym answered 23/6, 2015 at 21:38 Comment(3)
I think this will help you #7952230Apothem
Although the solution cleared a lot of things for me, I am not initializing my fragments from the activity. My FragmentPageAdapter is doing that. So, I am not sure how do I save and restore my fragments in my activity.Heteronym
Hi Buddy, just set configchanges = screensize in the manifest file and it will not reload the fragments and the current state will be retained. Hope that helps :)Maisel
H
6

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.

Heteronym answered 24/6, 2015 at 23:15 Comment(2)
If the nowDataList is the data of the adapter, it's better to use a Loader instead. A list can be very long, so much that it can't fit well inside the bundle, and can cause performance issues.Dalessandro
@GauravPandey here the question is how you restore the fragment of view pager ? If you are creating new instance of fragment when activity is recreated, you have two instances of fragment, one is newly created fragment and second one was old one that is restored one.Trover
L
13

When the ViewPager saves its state, it calls saveState() on its adapter. Similarly, when the ViewPager goes to restore its state, it calls restoreState on the adapter.

You could implement these methods, but that's already been done. Simply extend FragmentStatePagerAdapter instead of FragmentPagerAdapter and you get those method implementations for free.

If you extend FragmentStatePagerAdapter then implement onSaveInstanceState() and restore the state in onCreateView() for your Fragment classes, all should work as you expect.

Leighton answered 24/6, 2015 at 6:14 Comment(5)
An example with code would be extremely helpful here :-)Biggerstaff
This helped a lot in a similar situation. It should be the accepted answer.Wehrle
Restore is automatically done but what about view pager within fragment and I want to get the old reference of adapter as it is automatically handled.Trover
The docs for FragmentStatePagerAdapter have an entire working example: developer.android.com/reference/android/support/v4/app/…Leighton
But it has no example of saving and restoring stateYamashita
H
6

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.

Heteronym answered 24/6, 2015 at 23:15 Comment(2)
If the nowDataList is the data of the adapter, it's better to use a Loader instead. A list can be very long, so much that it can't fit well inside the bundle, and can cause performance issues.Dalessandro
@GauravPandey here the question is how you restore the fragment of view pager ? If you are creating new instance of fragment when activity is recreated, you have two instances of fragment, one is newly created fragment and second one was old one that is restored one.Trover

© 2022 - 2024 — McMap. All rights reserved.