Android DialogFragment 在屏幕旋转时崩溃

标签 android exception android-fragments nullpointerexception dialog

我有一个 DialogFragment 类。每次显示时我都必须设置监听器(我的应用程序中有多个案例)。

但是当我旋转屏幕时,mListener 变为空,并且当我单击按钮时出现 NullPointerExcpetion。我无法在 Activity 中实现监听器,因为此对话框有几种情况,每种情况都有不同的操作。

自定义对话框类:

MyDialogListener mListener;

public void show(FragmentManager fm, MyDialogListener listener) {
    mListener = listener;
    super.show(fm, "MyDialog");
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new AlertDialog.Builder(getActivity())
            .setTitle("Title")
            .setPositiveButton(android.R.string.ok, new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int whichButton) {
                    mListener.onDialogPositiveClick();
                    // NullPointerException after a screen rotate
                }
            })
            .setNegativeButton(android.R.string.cancel, null)
            .create();
}

Activity 类:

public void showMyFirstDialog() {
    new CutsomDialog().show(getFragmentManager(), mFirstListener);
}

public void showMySecondDialog() {
    new CutsomDialog().show(getFragmentManager(), mSecondListener);
}

最佳答案

您不能保留 Fragment(包括 DialogFragment)的实例字段。让本地数据在配置更改后仍然存在的机制是将 fragment 的参数设置为包含您的数据的 Bundle;此 bundle 将在配置更改后继续存在。

首先,去掉show()方法;这不是正确的方法。相反,您可以这样做:

DialogFragment frag = new MyDialogFragment();
Bundle args = new Bundle();
args.putString("TITLE", "Dialog Title Goes Here");
args.putString("MESSAGE", "This is a dialog messaage");
frag.setArguments(args);

frag.show();

然后您可以在创建 AlertDialog 时检索标题和消息:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    Bundle args = getArguments();
    String title = args.getString("TITLE");
    String message = args.getString("MESSAGE");

    // set up and return the alert dialog as before
}

处理 DialogListener 稍微复杂一些。您不希望在配置更改时持有对它的引用,因为它会导致返回到被破坏的 Activity 。相反,您可以安排从 fragment 的 onAttach() 方法内的 Activity 中检索监听器:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    // now cast activity to your activity class and get a reference
    // to the listener
}

您可能需要稍微更改您的 Activity 类别才能使其正常工作。如果您在许多 Activity 中使用此对话 fragment ,那么在这里定义 Activity 可以实现以请求监听器的接口(interface)特别有用。它看起来像这样:

public interface DialogListenerProvider {
    DialogListener getDialogListener();
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    if (activity instanceof DialogListenerProvider) {
        mListener = ((DialogListenerProvider) activity).getDialogListener();
    } else {
        // throw an error
    }
}

关于Android DialogFragment 在屏幕旋转时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27725836/

相关文章:

delphi - 在delphi 7中, `try ... except raise; end;`有意义吗?

java - Android - 来自 ArrayAdapter 的 fragment

Javascript,智能手机视频检测?

java - 执行一些 Action 并根据时间重复这些 Action

android - BufferQueue 已被放弃 : When playing video with TextureView

Powershell 异常 : Not enough quota is available to process this command

java - 任何用于将 Java/Android 中的原始图像(如 DNG)转换为 JPG 格式的 API 或代码

python - 在 Dart 中,Python 的 try...catch...else 最惯用的替代方法是什么?

android - 当子 recyclerview 滚动到最后一项时禁用 ViewPager 分页

android - fragment 中的错误加载微调器