user3533397
user3533397

Reputation: 191

Access from DialogFragment to host Activity's views

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

Answers (1)

phatnhse
phatnhse

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.

  1. Why don't you use the same approach to your fragment, where is mActivity in your onCreateDialog. Btw, please check null for mActivity before doing any transactions.

enter image description here

  1. Using yourDialogFragment.show() explicitly run this function:

enter image description here

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.

  1. Why don't you inflate view at onCreateView? (You don't have to do it in onCreateDialog)

enter image description here

Upvotes: 1

Related Questions