Fragments, DialogFragment, and Screen Rotation

2019-01-12 23:51发布

I have an Activity that calls setContentView with this XML:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal"
    >
    <fragment android:name="org.vt.indiatab.GroupFragment"
        android:id="@+id/home_groups"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1" />
            <..some other fragments ...>
</LinearLayout>

The GroupFragment extends Fragment, and all is well there. However, I show a DialogFragment from within GroupFragment. This shows correctly, HOWEVER when the screen rotates, I get a Force Close.

What's the proper way to display a DialogFragment from within another Fragment other than DialogFragment.show(FragmentManager, String)?

9条回答
beautiful°
2楼-- · 2019-01-13 00:18

There's a bug in the compatibility library that can cause this. Try putting this in you dialogfragment:

@Override
public void onDestroyView() {
  if (getDialog() != null && getRetainInstance())
    getDialog().setOnDismissListener(null);
  super.onDestroyView();
}

I also suggest setting your dialogfragment as retained, so it won't get dismissed after the rotation. Put "setRetainInstance(true);" e.g. in the onCreate() method.

查看更多
Anthone
3楼-- · 2019-01-13 00:21

I encountered this problem and the onDestroyView() trick wasn't working. It turned out that it was because I was doing some rather intensive dialog creation in onCreate(). This included saving a reference to the AlertDialog, which I would then return in onCreateDialog().

When I moved all of this code to onCreateDialog() and stopped retaining a reference to the dialog, it started working again. I expect I was violating one of the invariants DialogFragment has about managing its dialog.

查看更多
Juvenile、少年°
4楼-- · 2019-01-13 00:23

I used a mix of the presented solutions and added one more thing. This is my final solution:

I used setRetainInstance(true) in the onCreateDialog; I used this:

public void onDestroyView() {
    if (getDialog() != null && getRetainInstance())
        getDialog().setDismissMessage(null);
    super.onDestroyView();
}

And as a workaround of the savedInstanceState not working, I created a private class called StateHolder (the same way a holder is create for a listView):

private class StateHolder {
    String name;
    String quantity;
}

I save the state this way:

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    super.onSaveInstanceState(savedInstanceState);
    stateHolder = new StateHolder();
    stateHolder.name = actvProductName.getText().toString();
    stateHolder.quantity = etProductQuantity.getText().toString();
}

In the onDismiss method I set the stateHolder back to null. When the dialog is created, it verifies if the stateHolder isn't null to recover the state or just initialize everything normally.

查看更多
登录 后发表回答