DialogFragment.dismiss与NullPointerException崩溃

Lux*_*ode 24 android android-fragments

我正在做一些后台工作并在我这样做时显示DialogFragment.完成我的工作并调用相关的回调后,我将关闭该对话框.当我这样做时,我在Android源代码中遇到了由NPE引起的崩溃,这里:

void dismissInternal(boolean allowStateLoss) {
        if (mDialog != null) {
            mDialog.dismiss();
            mDialog = null;
        }
        mRemoved = true;
        if (mBackStackId >= 0) {
            getFragmentManager().popBackStack(mBackStackId,
                    FragmentManager.POP_BACK_STACK_INCLUSIVE);
            mBackStackId = -1;
        } else {
            FragmentTransaction ft = getFragmentManager().beginTransaction();
            ft.remove(this);
            if (allowStateLoss) {
                ft.commitAllowingStateLoss();
            } else {
                ft.commit();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

特别是在线: FragmentTransaction ft = getFragmentManager().beginTransaction();

pre*_*ela 15

当您在调用show()之前调用dismiss()时,也可能会发生这种情况,如Sogger所说.

在构造Dialog对象之后但在未显示对话框之前,如果(mDialog!= null)可以传递并且将发生NullPointerException.

当您检查mDialog是否为null时,

if (mDialog != null) {
    mDialog.dismiss();
    mDialog = null;
}
Run Code Online (Sandbox Code Playgroud)

添加更多条件,如下所示,

if ((mDialog != null) && mDialog.isAdded() && mDialog.isResumed()) {
    mDialog.dismiss();
    mDialog = null;
}
Run Code Online (Sandbox Code Playgroud)

我认为mDialog.isAdded()条件可能就够了......


Rus*_*hyn 11

最简单的解决方案是在调用"dismiss()"方法之前检查"getFragmentManager()"是否为"null".你也可以扩展"DialogFragment"类并覆盖方法"dismiss()"来检查它:

@Override
public void dismiss()
{
    if (getFragmentManager() != null) super.dismiss();
}
Run Code Online (Sandbox Code Playgroud)


ofe*_*iko 7

我知道这条消息已经过时但是我遇到了类似的情况,我需要解决这个问题而不需要重构或更改大量代码.希望它对某些人有用

   package com.example.playback;

import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class SaferDialogFragment extends DialogFragment {

    private boolean allowStateLoss = false;
    private boolean shouldDismiss = false;

    public SaferDialogFragment() {
    }

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

    @Override
    public void onStart() {
        super.onStart();
        //check if we should dismiss the dialog after rotation
        if (shouldDismiss) {
            if (allowStateLoss)
                dismissAllowingStateLoss();
            else
                dismiss();
        }
    }

    @Override
    public void dismiss() {
        if (getActivity() != null) { // it's "safer" to dismiss
            shouldDismiss = false;
            super.dismiss();
        } else {
            shouldDismiss = true;
            allowStateLoss = false;
        }
    }

    @Override
    public void dismissAllowingStateLoss() {
        if (getActivity() != null) { // it's "safer" to dismiss
            shouldDismiss = false;
            super.dismissAllowingStateLoss();
        } else
            allowStateLoss = shouldDismiss = true;
    }

    //keeping dialog after rotation
    @Override
    public void onDestroyView() {
        if (getDialog() != null && getRetainInstance())
            getDialog().setDismissMessage(null);
        super.onDestroyView();
    }



    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        /** omitted code **/
        return super.onCreateView(inflater, container, savedInstanceState);
    }
}
Run Code Online (Sandbox Code Playgroud)


Bar*_*rak 5

我敢打赌,你发布的代码来自后台线程......不允许你从UI线程以外的任何地方更新UI.

您可以使用onPostExecute()或runOnUiThread()来实现您的目标(如果我的猜测是正确的)

  • 我考虑过这个.但是,即使我调用了getActivity(),我也得到了相同的结果.虽然我还没有尝试过设置AsyncTask但是runOnUiThread (3认同)