【问题标题】:Application crash when rotation is changed using setRetainInstance(true) in fragments在片段中使用 setRetainInstance(true) 更改旋转时应用程序崩溃
【发布时间】:2014-10-02 16:10:10
【问题描述】:

我想要纵向和横向模式的不同布局。此外,我希望我的片段在方向发生变化时保存它们的状态。这里是layout\activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

它是layout-land\activity_main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <fragment
        android:id="@+id/fragment1"
        android:name="com.example.fragmentorientationchangetest.Fragment1"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <fragment
        android:id="@+id/fragment2"
        android:name="com.example.fragmentorientationchangetest.Fragment2"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

</LinearLayout>

这里是MainActivity

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (findViewById(R.id.container) != null) {

            if (savedInstanceState != null) {
                return;
            }
            Fragment1 fragment1 = new Fragment1();
            getFragmentManager().beginTransaction()
                    .add(R.id.container, fragment1, "tag1").commit();
        }

    }

它是Fragment1:

public class Fragment1 extends Fragment{

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View  view = inflater.inflate(R.layout.fragment1, container, false);

        return view;
    }

}

Fragment2 与 Fragment1 相同。

但是,当我以纵向模式开始并旋转到横向模式时,应用程序崩溃了。问题是因为使用了setRetainInstance(true),它保存了对R.id.container的引用,但是横向布局中不存在这个容器,这是输出:

10-02 15:52:50.679: E/AndroidRuntime(2531): FATAL EXCEPTION: main
10-02 15:52:50.679: E/AndroidRuntime(2531): Process: com.example.fragmentorientationchangetest, PID: 2531
10-02 15:52:50.679: E/AndroidRuntime(2531): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.fragmentorientationchangetest/com.example.fragmentorientationchangetest.MainActivity}: 
    java.lang.IllegalArgumentException: No view found for id 0x7f090000 (com.example.fragmentorientationchangetest:id/container) for fragment Fragment1{52874ecc #0 id=0x7f090000 tag1}

但根据this,我必须在片段中使用onRetainInstance 来处理方向更改。我现在该怎么办?

提前致谢!

【问题讨论】:

    标签: android android-fragments fragment android-orientation android-configchanges


    【解决方案1】:

    在这一行:

    getFragmentManager().beginTransaction()
            .add(R.id.container, fragment1, "tag1").commit();
    

    您正在将 Fragment 添加到 ID 为 container 的 ViewGroup。当 Activity 被销毁并重新创建时,它将尝试将该 Fragment 重新附加到 ID 为 container 的 ViewGroup。但是,在您的横向布局中,您没有container ViewGroup——您有一个在 XML 中定义的片段。替换:

    <fragment
        android:id="@+id/fragment1"
        android:name="com.example.fragmentorientationchangetest.Fragment1"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />
    

    与:

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />
    

    以便 Activity 能够重新附加 Fragment。

    【讨论】:

    • 但是如果我在fragment2的纵向模式下旋转屏幕,它将被添加到左侧窗格中。
    • 嗯,确实如此。我想这就是为什么他们在示例代码中为此使用新的 Activity 而不是交换片段的原因。也许最简单的解决方法是让两个具有不同 ID 的纵向框架布局?然后在同一个事务中隐藏()第一个片段并添加()新片段?
    • 是的,正如你所说,我认为可以通过使用两个动态覆盖的框架布局来实现。但是,如果没有其他方便的解决方案,我真的会感到惊讶,因为这可能并不罕见。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-05
    相关资源
    最近更新 更多