1

我认为我的应用程序中发生的事情的说明最适合这个问题。

用户登录后,他们将被带到 MainActivity。这包含一个ActionBar带有选项卡的选项卡,默认情况下会选择一个选项卡并且用户会看到....

    container1              container2

CompanyName: <EditText> |               |
ProjectName: <EditText> |     Welcome   |
   <SearchButton>       |               |

当用户填写这些表格并单击他们看到的搜索按钮时......

  container1             container2

   <ListView>       |                  |
   BasicInfo        |     Welcome      |
   Assessment       |                  |
   Signature        |                  |

当用户单击“评估”时,他们会看到

   container1             container2

   <ListView>       |     Question#1   |
   BasicInfo        |     Question#2   |
   Assessment       |     Question#3   |
   Signature        |     Question#4   |

现在,当评估fragment膨胀时,它会执行并为来自 的问题AsyncTask创建。现在,当用户在此屏幕上时,我不希望更改屏幕方向来再次执行网络请求。所以我把像这样的评估ViewsJSONAsyncTasksetRetainInstance(true);Fragment

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

        view = inflater.inflate(R.layout.fragment_assessment, container, false);
        ab = getActivity().getActionBar();
        infoList = new ArrayList<HashMap<String, String>>();
        allRadio = new ArrayList<RadioGroup>();
        allImageButton = new ArrayList<ImageButton>();
        allSpinner = new ArrayList<Spinner>();
        allEdit = new ArrayList<EditText>();
        allCheck = new ArrayList<CheckBox>();

        new Load().execute();
        setRetainInstance(true);
        return view;
    }

然而,当我在评估中翻转屏幕时,Fragment它不仅不会保存布局,还会将我返回给Activity看起来像这样的父级

    container1              container2

CompanyName: <EditText> |               |
ProjectName: <EditText> |     Welcome   |
   <SearchButton>       |               |

不知道我做错了什么。可能是我fragment的 inXML命名不正确,或者容器命名不正确。这里有代码。

容器 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:id="@+id/MainLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false"
    android:orientation="horizontal" >

    <LinearLayout
        android:id="@+id/header_fragment_container"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1.2"
        android:background="@drawable/green_gradient"
        android:orientation="vertical" >
    </LinearLayout>

    <LinearLayout
        android:id="@+id/content_fragment_container"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="2"
        android:background="@drawable/twoglobe_line"
        android:orientation="vertical"
        android:scrollbars="vertical" >
    </LinearLayout>

</LinearLayout>

评估片段 XML

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/basic_info_scroll"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/twoglobe_line"
    android:gravity="center"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/gen_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:orientation="vertical" >

        <LinearLayout
            android:id="@+id/add"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="5dp"
            android:layout_marginTop="10dp"
            android:orientation="vertical" >
        </LinearLayout>
    </LinearLayout>

</ScrollView>

那么我是在期待一个不切实际的结果setRetainInstance(true);还是我做错了?任何帮助表示赞赏。

4

3 回答 3

2

我不知道这是否是正确的方法,但这是我这样做的方式,它对我有用。

在我的布局中,我没有片段本身,我只有可以容纳它们的容器。然后,在我的应用程序开始时,我会查看我的任何片段是否已经加载(它们将在平板电脑布局中),如果没有,我会查看 savedState 包中是否有任何内容。如果那个 Bundle 是空的,那么我知道我的应用程序是第一次启动,我可以加载我的“home”片段。否则我在里面放了一个钥匙,onSaveInstanceState()让我知道要加载哪个片段。所以我会让 FragmentManager 将其中一个加载到容器中。

于 2013-06-10T23:15:44.153 回答
1

对于第一个屏幕,我会使用单独的活动。CaseyB 的答案非常好,实际上我也是这样处理的(现在,当你有很多方向变化时,在后台有一些东西,你会强制关闭,但这是不可避免的)。我要做的是第一个屏幕,使其成为自己的活动,然后调用第二个 FragmentActivity 并使左侧的片段静态(意思是在 XML 中定义它)。这样你就不用担心了。然后,您可以专注于正确的片段。如果您设置了 setRetainInstance,那么您不必担心重新创建视图。但是,如果它进入后台,那么您将失去一切。它从不调用 onDestroy,只调用 onDetach。并且 onCreate 仅在第一次创建片段时调用。所以,我会完全避免使用 onCreate,

更新 - 使用 onCreate() 方法设置 setRetainInstance(true) 并调用您的 JSON 和网络代码来创建视图。在这里做这件事很重要,这样它只会被调用一次。这应该完全适用于方向更改和片段之间的来回切换(后台堆栈将起作用,只是您不能在后台堆栈中将其设置为retainInstance。这是我的错字)。

然后,当片段恢复时,您想要调用的任何其他代码,使用 onAttach() 因为 onCreate() 不会被调用,因为它从未被破坏

然后,为了再次控制您的项目,您不能使用 getActivity().findViewById(),您必须使用 this.getView().findViewById()。我不知道为什么会这样(因为您会认为它会附加到活动视图组,但事实并非如此)。那应该是你唯一应该打的嗝。除此之外,它应该可以正常工作。

于 2013-06-10T23:48:42.773 回答
1

我实际上还没有弄清楚如何正确使用这种setRetainInstance()方法。我不得不暂时使用

android:configChanges="orientation|keyboardHidden|screenSize

在我的清单中。我从多个人那里听说,这是不鼓励的,而且是错误的做法。所以这个话题仍然是开放的,我将接受任何正确说明我应该如何正确使用这段代码的答案。

于 2013-06-10T23:50:56.657 回答