我有一个显示两个 fragment 的 Activity :

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

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

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

    重现步骤:
  • 启动应用程序。
  • 检查 CheckBox 并在 EditText 中输入一些文本
  • Button 启动 Fragment2
  • 旋转设备
  • 再次旋转设备
  • 按设备上的 Back 按钮(或模拟器上的 ESC)返回 Fragment1
  • 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();
    }
    

    最佳答案

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

    关于android - 将设备旋转两次时, fragment 会失去其状态,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10382844/

    10-09 01:34