I'm getting a NullPointerException for my listener in my class, even though everything should be working fine. I followed Coding in Flow's tutorial for the custom dialog, rewatched it a few times and checked source code and I didn't miss anything. here's the code
Fragment the dialog is called from
public class FragmentMain extends Fragment implements CustomDialog.DialogListener {
.
.
.
private int timeLimit = 0;
private Button dialogOpen;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
.
.
.
dialogOpen.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DialogDashboard dialogDashboard = new DialogDashboard();
dialogDashboard.show(getActivity().getSupportFragmentManager(), "notif_dialog");
}
}); //dialog called here
return view;
}
//getting text from spinner in dialog
@Override
public void applyText(String time) {
switch (time) {
case "30 Minutes":
timeLimit = 30;
case "1 Hour":
timeLimit = 60;
case "2 Hours":
timeLimit = 120;
case "4 Hours":
timeLimit = 240;
case "5 Hours":
timeLimit = 300;
}
}
}
Dialog Code:
public class CustomDialog extends AppCompatDialogFragment {
private Button confirmButton;
private Spinner spinner;
private DialogListener listener;
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(),
R.style.NotificationAlertDialog);
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.custom_dialog_notif, null);
confirmButton = view.findViewById(R.id.dialogButton);
spinner = view.findViewById(R.id.dialogSpinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity(),
R.array.spinner_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
confirmButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String time = spinner.getSelectedItem().toString();
listener.applyText(time); // says listener is null when I just do e.printStackTrace();
dismiss();
}
});
builder.setView(view)
.setCancelable(true);
return builder.create();
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
try {
listener = (DialogListener) context;
} catch (Exception e) {
e.printStackTrace();
throw new ClassCastException(context.toString() +
"must implement dialog listener"); // this says if the listener is null, but even if it's implemented it returns null...
}
}
public interface DialogListener {
void applyText(String time);
}
}
Root cause
You got NPE because onAttach()
callback is called when the fragment is attached to its host/activity. The context
param is the activity itseft, not the FragmentMain.
Solution
Step 1: When you click on the open dialog button in FragmentMain.
CustomDialog dialogDashboard = new CustomDialog();
dialogDashboard.show(getChildFragmentManager(), "notif_dialog");
Step 2: Modify the code in CustomDialog
Remove this code
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
try {
listener = (DialogListener) context;
} catch (Exception e) {
e.printStackTrace();
throw new ClassCastException(context.toString() +
"must implement dialog listener");
}
}
When users click on the confirm button.
String time = spinner.getSelectedItem().toString();
Fragment fragment = getParentFragment();
if (fragment instanceof CustomDialog.DialogListener) {
listener = (DialogListener) fragment;
listener.applyText(time);
}
dismiss();
Thank you so much! Sorry for the miss match names, I was renaming it so it was more clear in the post.