Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird fragment lifecycle error

EDIT

So it seems that my Fragment is retained in the FragmentManager which tries to reinitialize it. Still not sure why it isn't destroyed with the Activity. As for the loading message, this is displayed when the ListView does not have an adapter set. I however, set the adapter items in onCreate and onResume so I'm not sure why this loading screen is showing. Still open to any explanations of this behavior

Original

I'm playing around with fragments and noticed a weird error that is popping up when I change the orientation of the screen. This error should not be happening though because all the data is recreated in the onCreate when the screen orientation is changed. Also, the fragment onResume() is called twice after the rotation. Here's my steps for creating the error and how the debugger is hitting the functions.

  • Activity: onCreate()
  • Activity: onResume()
  • Fragment: onResume()
  • Rotate Screen
  • Activity: onCreate()
  • Activity: onResume()
  • Fragment: onResume() (items are null even though Activity.onResume() set them)
  • Fragment: onResume() (items are not null, why is this being called twice?)

After this last fragment onResume is hit, the tablet displays a "Loading..." message and icon. Why is the data not displayed in the list any more? My suspicions are that the onCreate is creating a second fragment. The first fragment looses its data because of the orientation destroying the views, the second fragment gets the data and the loading screen is the first fragment with no data items and the second fragment is hidden. I may be wrong. Why aren't the fragments all destroyed when the screen is rotated like the Activity? Please do not critique the code unless its to solve this specific issue. I'm not actually making an app, I'm experimenting with fragment functionality. Thanks!

Main Activity

private ArrayList<Object> items = new ArrayList<Object>();
private MyListFragment mylistFragment;

public MainActivity() {
    items.add("Hello");
    items.add("World");
    items.add("Goodbye");
}

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    FragmentManager fm = getFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();

    mylistFragment = new MyListFragment();
    mylistFragment.setItems(items);

    ft.add(R.id.container, mylistFragment);
    ft.commit();
}

@Override
public void onResume() {
    super.onResume();

    mylistFragment.setItems(items);
    mylistFragment.getListView().setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Toast.makeText(MainActivity.this, ((TextView)view).getText(), Toast.LENGTH_LONG).show();
        }

    });
}

List Fragment

private List<Object> items = null;
private Boolean isSet = false;

@Override
public void onResume() {
    super.onResume();
    if( !isSet && items != null) {
        setListAdapter(new ArrayAdapter<Object>(getActivity(), R.layout.item, items));
        isSet = true;
    }
}

public void setItems(List<Object> items) {
    this.items = items;
    if( this.isResumed() ) {
        setListAdapter(new ArrayAdapter<Object>(getActivity(), R.layout.item, items));
        isSet = true;
    } else {
        isSet = false;
    }
}
like image 271
Spidy Avatar asked May 03 '11 02:05

Spidy


1 Answers

The FragmentManager will automatically recreate the Fragment for me. However, the data inside them needs to be reinitialized. Therefore my code was creating a second fragment. The loading screen was because the first fragment no longer had its adapter of items and the second fragment was hidden. What a headache, I almost think the FragmentManager should destroy the Fragments so you can recreate them with the data they hold.

like image 77
Spidy Avatar answered Oct 11 '22 11:10

Spidy