0

We have a web service which serves up an XML file via a HTTP Post.

I am downloading and parsing this xml file into an object to populate some views inside a couple of fragments held in a FragmentPagerAdapter. I get this XML file via an AsyncTask and it tells my fragments the process has finished via a listener interface.

From there, I populate the view inside the fragment with data returned from the web service. This is all fine until the orientation changes. From what I understand, the ViewPager's adapter is supposed to retain the fragments it's created, which is fine, and which I want to happen, and I know the fragment's onCreateView method is still called to return the view. I've spent the last day or so hunting through posts here and the Google docs etc and I can't find a concrete method that lets me do what I want to do: retain the fragment, and it's already populated view so that I can simply restore it when the orientation changes and avoid unneccesary calls to the web service.

Some code snippets:

In the main activities onCreate:

mViewPager = (ViewPager) findViewById(R.id.viewpager);
if (mViewPager != null) {
    mViewPager.setAdapter(new PagerAdapter(getSupportFragmentManager()));
}

if (savedInstanceState == null) {
    if (CheckCredentials()) {
        Refresh(0,0);
    } else {
        ShowCredentialsDialog(false);
    }
}

Refresh method in main activity...

public void Refresh(Integer month, Integer year) {
    if (mUpdater == null) {
        mUpdater = new UsageUpdater(this);
//        mUpdater.setDataListener(this);
    }

    if (isConnected()) {
        mUpdater.Refresh(month, year);
        usingCache = false;
        mProgress.show();
    } else {
        mUpdater.RefreshFromCache();
        usingCache = true;
    }
}

This is the entire Fragment in question, minus some of the UI populating code as it's not important to show the setting of text in textviews etc...

public class SummaryFragment extends Fragment implements Listeners.GetDataListener {

    private static final String KEY_UPDATER = "usageupdater";
    private UsageUpdater mUpdater;
    private Context ctx;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        this.ctx = activity;
    }

    private View findViewById(int id) {
        return ((Activity)ctx).findViewById(id);
    }

    public void onGetData() {
        // AsyncTask interface method, will be called from onPostExecute.
        // Populate view from here
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        View view = inflater.inflate(R.layout.fragment_usagesummary, container, false);
        mUpdater = (UsageUpdater) getArguments().getSerializable(KEY_UPDATER);
        mUpdater.setDataListener(this);
        return view;
    }
}

If I understand any of this 'issue' it's that I'm returning an empty view in onCreateView but I don't know how to retain the fragment, return it's view prepopulated with data and manage all web service calling from the main activity.

In case you can't tell, Android is not a primary language for me and this probably looks a shambles. Any help is appreciated I'm getting rather frustrated.

Karl
  • 3,394
  • 2
  • 22
  • 31

1 Answers1

0

If you're not using any alternative resources when the Activity is re-created, you could try handling the rotation event yourself by using configChange flags in your AndroidManifest:

<activity
    ...
    android:configChanges="orientation|screenSize"
    ... />

There is no way to keep the same, pre-populated Views if your Activity is re-created since this would cause a Context leak:

http://www.curious-creature.org/2008/12/18/avoid-memory-leaks-on-android/

sddamico
  • 2,130
  • 16
  • 13
  • I've read that this is against best practice so I am avoiding doing it. I also don't want to retain a portrait view when the phone is in a landscape orientation. I know what I want to do can be done because plenty of applications do it, but I'm trying to find the correct method for achieving it. – Karl Aug 05 '13 at 02:47
  • Then what you'll likely want to do is put a `Fragment` in your MainActivity layout that contains your `ViewPager` and `FragmentPagerAdapter` as well as the data backing the Adapter. in the top level Fragment's `onSaveInstanceState()`, save the data backing your current view: ... outState.putString(key, string); // etc, etc for all the data backing your view ... then in onCreateView() of the top level Fragment: ... if(savedInstanceState != null){ // restore state by recreating your adapter, by changing the selected page, putting data into the fragment, etc } – sddamico Aug 05 '13 at 03:04
  • That was in reply to @sddamico's comment, not the original answer. – Karl Nov 17 '13 at 20:17