【问题标题】:ListFragment with setRetainInstance(true) not showing the listview after a screen rotation带有 setRetainInstance(true) 的 ListFragment 在屏幕旋转后不显示列表视图
【发布时间】:2013-08-06 22:04:15
【问题描述】:

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

我想请你在这个主题上提供一些指导,因为它是我最好的选择。

我将粘贴活动、片段和布局的代码:

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 后创建片段,当片段创建时,它会执行加载程序并设置视图。一旦加载器完成加载,它就会毫无问题地更新视图。

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

我已尝试将适配器的配置移至 onViewCreated,但没有成功。

【问题讨论】:

    标签: android android-listview android-listfragment


    【解决方案1】:

    如果您使用的是保留片段,则不应尝试更新该片段中的 UI:

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

    第 4.2 节:

    除此之外,您还可以使用 setRetainState(true) 方法调用 碎片上。这保留了片段之间的实例 配置更改,但仅在未将片段添加到时才有效 后台。谷歌不推荐使用这种方法 具有用户界面的片段。在这种情况下,数据必须是 存储为成员(字段)。

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

    【讨论】:

    • 感谢@Sheldon 提供的信息。我已经进行了更改,它与我的预期有点不同,但它现在可以工作了。
    • 没有问题 - 有时 UI 内容在保留的片段中确实有效,但既不保证也不推荐。
    • 不确定此语句来自何处,在保留片段中使用 UI 效果很好。我认为混乱来自一些提到可能的“内存泄漏”的帖子,如果片段保留对 View 对象的引用,这当然是不好的,因为 View 被销毁并与活动一起重新创建。结论,在保留的fragment中使用UI是没有问题的,只要你知道他们的life cycle differences。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多