android - 带有 setRetainInstance(true) 的 ListFragment 在屏幕旋转后不显示 ListView

标签 android android-listview android-listfragment

我正在尝试在 ListFragment 上使用 setRetainInstance(true),直到 onCreateView 为止,它就像一个魅力一样工作,类中的所有属性都被保留并且似乎没问题。但是一旦屏幕旋转并生成 View ,listView 就不会显示,尽管适配器和数据在那里。

我想就此主题向您寻求一些指导,因为我已经尽力了。

我将粘贴 Activity 、 fragment 和布局的代码:

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));
        }
    }

}

这是 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"/>

这是 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();

    }


}

这是 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>

如您所见,我只创建了一次检查 savedInstanceState 的 fragment ,当 fragment 被创建时,它会执行加载程序并设置 View 。一旦加载程序完成加载,它就会毫无问题地更新 View 。

只要我旋转模拟器的屏幕,就会只显示 content_list.xml 中的“hello_world”。

我尝试将适配器的配置移动到 onViewCreated 但没有成功。

最佳答案

如果您使用的是保留的 fragment ,那么您不应该尝试更新该 fragment 中的 UI:

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

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).

您可以将 UI 内容移动到不同的 fragment 或父 Activity 。

关于android - 带有 setRetainInstance(true) 的 ListFragment 在屏幕旋转后不显示 ListView ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18091338/

相关文章:

android - 我们可以设置它应该保留在内存中的 ListView 中的项目数,这样 ListView 就不会每次都回收

android - BLE - 我无法同时读取 2 个特性,一个是温度服务,另一个是电池服务

android ListView 将隐藏值从一个 Activity 传递到另一个

java - 使用 BaseAdapter 在 ListView 中显示 ArrayList

Android - 按下列表项 View 时弹出菜单?

android - Android Studio 中的列表 fragment

java - java中httpResponse返回null

android - 如何在 Android 中单击 ListView 行时使 ImageView 可见和不可见?

java - 传递给 List 的 ArrayAdapter 的 arraylist 应该是线程安全的吗?

android - 如何设置 ListFragment 自定义布局的分隔符(为空)