Reputation: 191
I've faced with such problem. In my app I have an Activity (MobileActivity) which contains some views (Spinners, TextViews and Button). When user clicks on the button, I need to open a Dialog (ConfirmDialog). In this Dialog, I need to show some data from MobileActivity's views (see code below). And sometimes in Play Console, I see crash reports with NullPointerException (I marked that row in my code). Where is the problem?
Thank you!
I supposed, that the problem can be in Activity's lifecycle methods. I tried next actions:
It didn't crash. So, the problem isn't in back|foreground?
Code from MobileActivity, which will open my DialogFragment
ConfirmDialog newFragment = new ConfirmDialog();
newFragment.show(getFragmentManager(), "Confirmation");
Code From ConfirmDialog
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = getActivity().getLayoutInflater();
View v = null;
Spinner s;
v = inflater.inflate(R.layout.confirm_mobile_layout, null);
builder.setView(v);
//next row marked in stacktrace as problem row
//Spinner with Id=acn_debit_mobile is placed on MobileActivity
s = getActivity().findViewById(R.id.acn_debit_mobile);
Spinner b = getActivity().findViewById(R.id.biller_mobile);
//other code
return builder.create();
}
And the stacktrace from Play Console
java.lang.RuntimeException:
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2814)
at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2892)
at android.app.ActivityThread.handleRelaunchActivity (ActivityThread.java:4763)
at android.app.ActivityThread.-wrap18 (Unknown Source)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1621)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loop (Looper.java:171)
at android.app.ActivityThread.main (ActivityThread.java:6635)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:823)
Caused by: java.lang.NullPointerException:
at ua.grant.smart.ConfirmDialog.onCreateDialog (ConfirmDialog.java:121)
at android.app.DialogFragment.onGetLayoutInflater (DialogFragment.java:406)
at android.app.Fragment.performGetLayoutInflater (Fragment.java:1325)
at android.app.FragmentManagerImpl.moveToState (FragmentManager.java:1279)
at android.app.FragmentManagerImpl.moveFragmentToExpectedState (FragmentManager.java:1562)
at android.app.FragmentManagerImpl.moveToState (FragmentManager.java:1623)
at android.app.FragmentManagerImpl.dispatchMoveToState (FragmentManager.java:3032)
at android.app.FragmentManagerImpl.dispatchActivityCreated (FragmentManager.java:2984)
at android.app.FragmentController.dispatchActivityCreated (FragmentController.java:178)
at android.app.Activity.performCreate (Activity.java:7090)
at android.app.Activity.performCreate (Activity.java:7075)
at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1215)
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2767)
I added onAttach and onDetach methods to store a reference to my host Activity (code below), and replaced getActivity() to mActivity in all places in my ConfirmDialog class. Will it solve this problem?
mActivity Activity;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mActivity = activity;
}
@Override
public void onDetach() {
super.onDetach();
mActivity = null;
}
Upvotes: 0
Views: 199
Reputation: 3930
Keeping activity instance and destroy it whenever the fragment is detached is a good approach to avoid NullPointerException
mActivity Activity;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mActivity = activity;
}
@Override
public void onDetach() {
super.onDetach();
mActivity = null;
}
But there are 2 things you might need to review.
mActivity
in your onCreateDialog
. Btw, please check null for mActivity
before doing any transactions.yourDialogFragment.show()
explicitly run this function:ft.commit()
schedules a commit of this transaction. The commit does not happen immediately. It will be scheduled as work on the main thread to be done the next time that thread is ready. So we can't ensure anything, it may cause IllegalStateException
for instance.
How about: commitAllowingStateLoss()
. But read the document carefully before using it. Take a look at this.
onCreateView
? (You don't have to do it in onCreateDialog
)Upvotes: 1