2

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

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

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

内容活动.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 ,但没有成功。

4

1 回答 1

1

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

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

第 4.2 节:

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

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

于 2013-08-06T22:34:22.157 回答