当旋转设备两次时,片段会丢失其状态

时间:2012-04-30 11:22:03

标签: android android-fragments

我有一个显示两个片段的活动:

  • 创建活动时,会显示Fragment1
  • 当用户按下Fragment1上的按钮时,会显示Fragment2,并添加到backstack。

片段很简单。 Fragment1包含CheckBoxEditTextFragment2包含简单的TextView。我也在片段的setRetainInstance(true)方法中调用onCreate(...)

问题Fragment1如果显示Fragment2且设备已旋转两次,则会失去其状态。但是,如果设备仅旋转一次,一切都会按预期工作。

重现的步骤:

  1. 启动应用程序。
  2. 选中CheckBox并在EditText
  3. 中输入一些文字
  4. Button启动Fragment2
  5. 旋转设备
  6. 再次旋转设备
  7. 按设备上的Back按钮(或模拟器上的ESC)返回Fragment1
  8. Fragment1丢失了其状态(复选框未选中且EditText为空)。 但是,如果您在Fragment1之后返回step#4 - Fragment1按预期保持其状态。

    问题出在哪里?所有代码都在下面,包括布局。

    main.xml中

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/placeholder"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    

    fragment1.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
        <CheckBox
            android:id="@+id/checkBox1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="CheckBox" />
    
        <EditText
            android:id="@+id/editText1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
        </EditText>
    
        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Start Fragment2" />
    
    </LinearLayout>
    

    fragment2.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Fragment #2" />
    
    </LinearLayout>
    

    FragmentTestActivity.java

    package fragmenttest.example.com;
    
    import android.app.Activity;
    import android.app.FragmentManager;
    import android.os.Bundle;
    
    public class FragmentTestActivity extends Activity implements FragmentListener {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            FragmentManager fm = getFragmentManager();
            if (fm.findFragmentByTag(Fragment1.TAG) == null) {
                fm.beginTransaction().replace(R.id.placeholder, new Fragment1(), Fragment1.TAG).commit();
            }
        }
    
        @Override
        public void onButtonClick() {
            FragmentManager fm = getFragmentManager();
            if (fm.findFragmentByTag(Fragment2.TAG) == null) {
                fm.beginTransaction().replace(R.id.placeholder, new Fragment2(), Fragment2.TAG).addToBackStack(Fragment2.TAG).commit();
            }
        }
    }
    

    Fragment1.java

    package fragmenttest.example.com;
    
    import android.app.Activity;
    import android.app.Fragment;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.Button;
    
    public class Fragment1 extends Fragment {
        public static final String TAG = Fragment1.class.getName();
        private FragmentListener mListener;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setRetainInstance(true);
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View root = inflater.inflate(R.layout.fragment1, container, false);
    
            Button button = (Button) root.findViewById(R.id.button1);
            button.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    mListener.onButtonClick();
                }
            });
    
            return root;
        }
    
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
    
            mListener = (FragmentListener) activity;
        }
    }
    

    Fragment2.java

    package fragmenttest.example.com;
    
    import android.app.Fragment;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    public class Fragment2 extends Fragment {
        public static final String TAG = Fragment2.class.getName();
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setRetainInstance(true);
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View root = inflater.inflate(R.layout.fragment2, container, false);
            return root;
        }
    }
    

    FragmentListener.java

    package fragmenttest.example.com;
    
    public interface FragmentListener {
        public void onButtonClick();
    }
    

1 个答案:

答案 0 :(得分:2)

可能是因为在恢复片段时未调用onCreate。 见:http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)