Frage

The question pretty much sums it up, I am trying to save my fragments so when I rotate the screen the application does not crash but I am not sure where or how to save my fragments, I have tried using a fragment manager and setting retainstate to true as well as checking the saved instance state.

This is my code : EventsActivty - Hosts the fragments

@Override
public void onCreate(Bundle savedInstanceState) {
    new AsyncLogin().execute(username, password);

    super.onCreate(savedInstanceState);

    username = getIntent().getStringExtra("username");
    password = getIntent().getStringExtra("password");
}

private List<Fragment> getFragments(){
    List<Fragment> fList = new ArrayList<Fragment>();

    EventListFragment eventListFragment = (EventListFragment)
         EventListFragment.instantiate(this, EventListFragment.class.getName());
    EventGridFragment eventGridFragment = (EventGridFragment) 
         EventGridFragment.instantiate(this, EventGridFragment.class.getName());

    fList.add(eventListFragment);
    fList.add(eventGridFragment);

    return fList;
}

The getFragments is called here, on the OnPostExecute of the AsyncTask

    protected void onPostExecute(JSONObject jsonObject) {
        try {
            getEvents(jsonObject);
            setContentView(R.layout.eventlist);
            List<Fragment> fragments = getFragments();
            pageAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
            ViewPager pager = (ViewPager)findViewById(R.id.viewpager);
            pager.setAdapter(pageAdapter);
       }

Fragment 1 : OnCreateView

 @Override
 public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    eventObjects = ((EventsActivity)getActivity()).getEventObjects();

    setRetainInstance(true);

    View view = inflater.inflate(R.layout.eventlist ,container,false);

    final ListView listView = (ListView) view.findViewById(R.id.listView);
    listView.setAdapter(new MyCustomBaseAdapter(getActivity(), eventObjects));
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> a, View v, int position, long id) {
            Object o = listView.getItemAtPosition(position);
            EventObject fullObject = (EventObject)o;
            System.out.println("asd");
        }
    });
    return view;
}
}

Fragment 2:

 @Override
 public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    setRetainInstance(true);

    View view = inflater.inflate(R.layout.eventgrid ,container,false);
    GridView gridView = (GridView) view.findViewById(R.id.eventgrid);
    gridView.setAdapter(new ImageAdapter(view.getContext())); // uses the view to get the context instead of getActivity().
    return view;
}
War es hilfreich?

Lösung

Actually, a FragmentActivity will automatically restore your fragments in onCreate().

Weird thing is, you call AsyncTask first, prior to calling through to super.onCreate() and retrieving username and password from the Intent.

Even having set that aside, that approach will make your activity spawn a new login task every time it's rotated.

Better way is to check savedInstanceState for null:

if (savedInstanceState == null) {
    // first launch
    new AsyncLogin().execute(username, password);
}
...

That way it's only going to run when Activity is created for the first time.

Second, you need to completely unbind login info from your activity. Make the AsyncTask return whatever login result you get to the Application and store it there. And your activity and fragments to retrieve that info from the Application - that way you get full control over you login procedure: you check whether there's an active session, if there isn't you check whether the AsyncTask is already running, if it isn't - you need to launch it. If it is - you need to wait for it to finish (show progress bar or something).

Andere Tipps

You should understand that retaining the fragments won't prevent the activity from being distroyed.

Now take a look here:

@Override
public void onCreate(Bundle savedInstanceState) {
     new AsyncLogin().execute(username, password);
     // ..... 
}

When a screen orientation change occurs, your activity is still destroyed. As a result a new AsyncTask is started. But when the old AsyncTask completes the job, it tries to deliver the result to the old activity, that was destroyed already. As a result this will cause a crash.

The solution would be to put the AsyncTask in the fragment itself. So that the instance to not be destroyed on orientation change.

See if this article can help you.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top