DialogFragment : NullPointerException (support lib

2020-02-21 07:59发布

问题:

I'm using the excellent ACRA library to receive error reports from my apps.

I'm receiving a lot of reports from customers concerning an NPE in DialogFragment, but Im unable to reproduce it :

java.lang.NullPointerException
at android.support.v4.app.DialogFragment.onActivityCreated(SourceFile:366)
at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:892)
at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1083)
at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1065)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(SourceFile:1844)
at android.support.v4.app.FragmentActivity.onStart(SourceFile:519)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1133)
at android.app.Activity.performStart(Activity.java:4475)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1929)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
at android.app.ActivityThread.access$600(ActivityThread.java:123)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)

The NPE happens inside the support library (@line 366):

353    @Override
354    public void onActivityCreated(Bundle savedInstanceState) {
           (...)
361        View view = getView();
362        if (view != null) {
363            if (view.getParent() != null) {
364                throw new IllegalStateException("DialogFragment can not be attached             to a container view");
365            }
366            mDialog.setContentView(view);
367        }

Im unable to reproduce the problem on any of my device (from 2.2 to 4.1.1). Since there's no reference to any of my code, is it a library bug?

回答1:

I have had to debug the same issue in a project.

Typically Dialog fragment is used as below

@Override
public Dialog onCreateDialog (Bundle savedInstanceState)
{
  //Create custom dialog
  return dialog;
}

Try updating it to the following

@Override
public Dialog onCreateDialog (Bundle savedInstanceState)
{
  //Create custom dialog
  if (dialog == null)
    super.setShowsDialog (false);

  return dialog;
}

This will prevent DialogFragment.onAtivityCreated() from executing methods on the null member variable mDialog.



回答2:

This is a relatively common crash that I've seen reported within StackOverflow, and it's due to the dialog not being created properly, causing mDialog to be null. The brute force method I initially used to prevent the crash:

@Override
public void onActivityCreated(Bundle arg0) {
    if (getDialog() == null ) {  // Returns mDialog
        // Tells DialogFragment to not use the fragment as a dialog, and so won't try to use mDialog
        setShowsDialog( false ); 
    } 
    super.onActivityCreated(arg0);  // Will now complete and not crash

}

While the above is probably better than a crash, this doesn't address the root cause of why the dialog failed to be created. There could be many reasons for that and that's what needs to be debugged.

In my situation, I found that I needed to implement DialogFragment's onCreateDialog() instead of onCreateView() to properly create the dialog 100% of the time. (onCreateView() almost always works to create the dialog, but I PROVED that there are reproducible corner cases where onCreateView() fails to work, causing mDialog to become null. On the other hand, I always found that onCreateDialog() properly created DialogFragment's dialog.)



回答3:

I had the NPE.

But surrounding the super.OnActivityCreated with a try/catch did not help.

What did help was the removal of a static field that was left over from copying an example. So, no static fields inside an overridden DialogFragment.



回答4:

DialogFragment.mDialog can be null if DialogFragment.dismiss() is called before onActivityCreated() is called.



回答5:

No it's not. This is the common error if the SetContentView crashes. setContentView calls the constructors of the Controls of your view. One throwed a nullPointerException.



回答6:

If you are overriding onCreateView(..) to instantiate the view of your DialogFragment you need to show it using a fragment transaction and put setShowsDialog to false to avoid this error. i.e:

            //Instantiate your DialogFragment and fragmentManager previously and then just do this:
            dialogFragment.setShowsDialog(false);
            FragmentTransaction fT = fragmentManager.beginTransaction();
            fT.add(0, dialogFragment, TAG);
            fT.commit();