0

I have a Fragment that brings up a PopupWindow when a Button is pressed. In this PopupWindow, there is a TextView and another Button. Pressing this Button puts the text in the TextView in the Clipboard and also shows a Toast.

All of my button OnClickListeners and view initializations are done in the Fragment's OnCreateView method.

If I bring up the PopupWindow and then go into multi-window mode (holding the "Overview" button on Nougat+), the PopupWindow will still be present with the TextView unchanged. But then, if I press the Button in the PopupWindow, I get a NullPointerException from my getActivity() call within the OnClickListener.

Relevant code:

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_balance_equation, container, false);

    // initialize PopupWindow assets
    popupView = inflater.inflate(R.layout.popupwindow_layout, null);
    copyButton = (Button) eqnView.findViewById(R.id.copy_button);

    myPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);

    copyButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            String equation = ((TextView) eqnView.findViewById(R.id.balanced_equation)).getText().toString();
            ClipData clip = ClipData.newPlainText("balanced equation", equation);
            clipboard.setPrimaryClip(clip);
            if (toast != null){
                toast.cancel();
            }
            // **Null Pointer Exception here**
            toast = Toast.makeText(getActivity(), "Equation Copied", Toast.LENGTH_SHORT);
            toast.show();
        }
    });
    return rootView;
}

Stack trace:

FATAL EXCEPTION: main
                                               Process: com.example.riesz.chemicalequationbalancer, PID: 14126
                                               java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
                                                   at android.widget.Toast.<init>(Toast.java:102)
                                                   at android.widget.Toast.makeText(Toast.java:260)
                                                   at com.example.riesz.chemicalequationbalancer.BalanceEquationFragment$2.onClick(BalanceEquationFragment.java:200)
                                                   at android.view.View.performClick(View.java:5612)
                                                   at android.view.View$PerformClick.run(View.java:22285)
                                                   at android.os.Handler.handleCallback(Handler.java:751)
                                                   at android.os.Handler.dispatchMessage(Handler.java:95)
                                                   at android.os.Looper.loop(Looper.java:154)
                                                   at android.app.ActivityThread.main(ActivityThread.java:6123)
                                                   at java.lang.reflect.Method.invoke(Native Method)
                                                   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
                                                   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)

EDIT:

Nivesh provided a solution but I don't fully understand why it works. It makes perfect sense that you can get an instance of the Activity by overriding onAttach() and store this globally for use later on. But why does the call to getActivity() not accomplish the same thing, especially since I used getActivity() multiple times in the same way and none of those calls raised an exception?

To see what I mean, here is my entire java file: https://pastebin.com/Z5cWrVZ4.

(I have implemented Nivesh's solution already here so this doesn't throw the exception. Changing the context parameter of Toast makeText() back to getActivity() in the copyButton OnClickListener throws the exception, as it did in my previous code snippet.)

Notice how my usage of Toasts in other OnClickListeners is exactly the same everything, yet only fails with the copyButton.

EDIT 2:

I have checked if getActivity() returns null in OnCreateView() and inside the copyButton listener: it is non-null in both cases. So then why is there even a NullPointerException?

Quantum Dot
  • 395
  • 1
  • 7
  • 12

1 Answers1

2

Make global object for activity like below:

private Activity activity;

@overide
OnAttach(Activity activity)
{
  this.activity = activity;
}

Use activity object anywhere in your fragment class.

nivesh shastri
  • 430
  • 2
  • 13
  • Hmm this worked. Could you explain the reasoning here? My understanding is that onAttach() is called before onCreateView() and allows me to get an instance of the Activity. But then this begs the question: what is getActivity() trying to do then..why isn't it able to accomplish the same thing? And also, I have used getActivity() to provide the Toast context in many other places in the exact same way (inside other OnClickListeners) and they all work fine before and after multi-window mode is activated. What's going on here? – Quantum Dot Aug 12 '17 at 05:23
  • it's a simple thing, when you write getActivity() means method of fragment called who give you instance of activity or onAttach() method give you activity instance directly without calling any method. Get instance of activity with getActivity() is heavy task. – nivesh shastri Aug 12 '17 at 09:39