Retaining list in list fragment on orientation change
Asked Answered
J

2

18

I have an app using fragments, all of which are contained in a single activity. The activity starts with a fragment containing a menu of buttons, all of which cause various listfragments to replace the original button/menu fragment.

My problem is that upon an orientation change, if the activity is displaying one of the listviews, it goes away and the button menu returns. I understand why this is happening... the activity is destroyed and re-created, but not how to work around it and maintain the list view/current fragment through the orientation change.

I've found setRetainInstance and the example of use here, but I can't figure out how to apply it to my situation with the button menu or the possibility that the fragment I want to retain could be one of several different ones.

Below is code simplified to show the main activity and one of the listfragments.

Any pointers in what to add where to make it so that the list fragment will be retained would be greatly appreciated.

Activity

public class Main extends FragmentActivity {
    private MainMenuFragment menu;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        menu = new MainMenuFragment();
        getSupportFragmentManager().beginTransaction().replace(R.id.pane, menu).commit();    
    }
}

ListFragment

public class ItemListFragment extends ListFragment {

    private TextView header;
    private TextView empty;
    private Button add;
    public static Cursor itemCursor;
    private GroceryDB mDbHelper;
    public static long mRowId;
    public static CheckCursorAdapter lists;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.common_list, container, false);
        header = (TextView) v.findViewById(R.id.header);
        empty = (TextView) v.findViewById(android.R.id.empty);
        header.setText(R.string.header_item);
        empty.setText(R.string.empty_items);
        return v;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        mRowId=0;
        mDbHelper = new GroceryDB(getActivity());
        mDbHelper.open();

        itemCursor = mDbHelper.fetchAllItems();
        getActivity().startManagingCursor(itemCursor);

        String[] from = new String[] { GroceryDB.ITEM_NAME };
        int[] to = new int[] { R.id.ListItem };
        lists = new CheckCursorAdapter(getActivity(),
                R.layout.listlayout_itemlist, itemCursor, from, to);
        setListAdapter(lists);        
    }
}
Jenninejennings answered 5/5, 2012 at 16:2 Comment(0)
R
35

how to work around it and maintain the list view/current fragment through the orientation change

You are blindly replacing the fragment every time onCreate() is called. Instead, only add/replace the fragment if savedInstanceState() is null. If it is not null, you are coming back from a configuration change, and your existing fragments will be recreated (or, if they were retained, they are already there).

setRetainInstance(true) means that the fragment itself will be retained across configuration changes, instead of being destroyed/recreated like the activity is. However, it will still be called with onCreateView(). In your code, that means that your data members of ItemListFragment would stick around, but you would still need to call setListAdapter() even if you do not requery the database.

Revareval answered 5/5, 2012 at 16:20 Comment(1)
Well, that was incredibly embarrassing (not to mention dumb of me). I know that I should check for savedInstanceState(), but for some reason I didn't do it this time and never even thought about it. Thanks for the quick reply.Jenninejennings
C
0

I know that this has been resolved a long time ago, but for the sake of people searching for a solution who have as much issues as I've (repeatedly) had with retaining lists during an orientation change I would like to add that you could also use a custom class which holds the list of data for your listadapter.

This way it keeps the data when recreating the activity (and listfragment) and you can just test to see if it has any data in your oncreate. If the list == null or the list.size < 0 you proceed as usual and get the data whatever way you normally get it. Otherwise you just set your listadapter with the data it already has.

To me this is a lot easier, and seeing as Eclipse automatically creates a similar DummyContent class for your data when creating an android master/detail flow project it basically only requires a change of the oncreate of your listfragment.

Coridon answered 29/4, 2014 at 13:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.