danielfranklinr
danielfranklinr

Reputation: 23

ListFragment with setRetainInstance(true) not showing the listview after a screen rotation

I'm trying to use the setRetainInstance(true) on a ListFragment, and up until the onCreateView it works like a charm, all the properties in the class are retained and seems to be ok. But as soon as the screen rotates and the view gets generated the listView is not being displayed, although the adapter and the data are there.

I would like to ask you for some guidance in this topic because it's taken the best of me.

I'll paste the code for the activities, fragments and layouts:

ContentActivity.java

public class ContentActivity extends SherlockFragmentActivity {

    private final String LOG_TAG = ContentActivity.class.getName();
    private ContentListFragment contentFragment = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // set the content layout
        setContentView(R.layout.content);

        if (savedInstanceState == null) {
            // Creates the fragment for the ContentList
            contentFragment = new ContentListFragment();
            // Add the fragment to the 'content_container' FrameLayout
            getSupportFragmentManager()
                    .beginTransaction()
                    .add(R.id.content_container, contentFragment,
                            getResources().getString(R.id.content_container))
                    .commit();
        } else {
            // If we're being restored from a previous state,
            // then we don't need to do anything and should return or else
            // we could end up with overlapping fragments.
            contentFragment = (ContentListFragment) getSupportFragmentManager()
                    .findFragmentByTag(
                            getResources().getString(R.id.content_container));
        }
    }

}

This is the layout for the ContentActivity content.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/content_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

This is the ContentListFragment.java

public class ContentListFragment extends SherlockListFragment implements
            LoaderCallbacks<HTTPRequestLoader.RESTResponse> {


    private final String LOG_TAG = ContentListFragment.class.getName();

    private static final int LOADER_PREFERENCES = 0x1f;
    private ContentListAdapter contentAdapter = null;
    private List<Content> contents = new ArrayList<Content>();

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

        View v = inflater.inflate(R.layout.content_list, container, false);
        Log.i(LOG_TAG, "onCreateView");
        contentAdapter = new ContentListAdapter(getActivity(),
                R.layout.content_block_item, contents);
        Log.i(LOG_TAG,
                "savedInstanceState==null size of the adapter in onCreateView "
                        + contentAdapter.getCount());
        Log.i(LOG_TAG, "savedInstanceState==null size of the contents "
                + contents.size());
        setListAdapter(contentAdapter);
        contentAdapter.notifyDataSetChanged();

        return v;
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
         setRetainInstance(true);
        // If there is no data, prepare the loader. Either re-connect with an
        // existing one,
        // or start a new one.
        getActivity().getSupportLoaderManager().initLoader(LOADER_PREFERENCES,
                null, this);
        Log.i(LOG_TAG, "onCreate");
    }

    @Override
    public Loader<RESTResponse> onCreateLoader(int id, Bundle params) {
        return ConnectionManager.getInstance().getPreferencesLoader(
                getActivity(), params);
    }

    @Override
    public void onLoadFinished(Loader<HTTPRequestLoader.RESTResponse> loader,
            HTTPRequestLoader.RESTResponse data) {
        int code = data.getCode();
        String json = data.getData();
        Log.i(LOG_TAG, "loaderFinished");
        // Check to see if we got an HTTP 200 code and have some data.
        if (code == 200 && !json.equals("")) {

            contentAdapter.clear();
            contents = ParserJson.getPreferencesFromJson(json);

            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
                contentAdapter.addAll(contents);
            } else {
                for (Content content : contents) {
                    contentAdapter.add(content);
                }
            }
            contentAdapter.notifyDataSetChanged();

        } else {
            // TODO: extract string
            Toast.makeText(
                    getActivity(),
                    "Failed to load Preferences data. Check your internet settings.",
                    Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onLoaderReset(Loader<RESTResponse> loader) {
    }

    public void deselectItems() {
        for (Content content : contents) {
            for (Section section : content.getSections()) {
                section.setSelected(false);
            }
        }
        contentAdapter.notifyDataSetChanged();

    }


}

Here's the content_list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hello_world" />

    <ListView
        android:id="@id/android:list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="@null" />

    <FrameLayout
        android:id="@+id/content_dialog"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >
    </FrameLayout>

</LinearLayout>

As you can see, I create the fragment only once checking the savedInstanceState, when the Fragment is created it executes a loader and sets the view. As soon as the loader finishes the load it uptades the view without problem.

As soon as I rotate the emulator's screen in shows only "hello_world" from the content_list.xml.

I've tried to move the configuration of the adapter to onViewCreated without success.

Upvotes: 2

Views: 1890

Answers (1)

IanB
IanB

Reputation: 3489

If you are using a retained fragment then you are not supposed to attempt to update the UI in that fragment:

http://www.vogella.com/articles/AndroidFragments/article.html#fragmentspersistence_configurationrestarts

section 4.2:

In addition to that you can use the setRetainState(true) method call on the fragments. This retains the instance of the fragments between configuration changes but only works if the fragments is not added to the backstack. Using this method is not recommend by Google for fragments which have an user interface. In this case the data must be stored as member (field).

You could move the UI stuff to a different fragment or to the parent activity.

Upvotes: 1

Related Questions