androidkotlinandroid-dialogfragment

Android DialogFragment getDialog() and getView() returning null


I've got a DialogFragment that I need to show from a Fragment. This is my DialogFragment:

class MyDialogFragment : DialogFragment() {
    companion object {
        @JvmStatic
        internal fun newInstance(): MyDialogFragment = MyDialogFragment()
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
        inflater.inflate(R.layout.my_dialog_fragment container, false)

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        view.findViewById<MaterialButton>(R.id.cancel_button)?.setOnClickListener { dismiss() }
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val builder = AlertDialog.Builder(requireActivity())
        val dialogView = requireActivity().layoutInflater.inflate(R.layout.my_dialog_fragment, null)
        builder.setView(dialogView)

        dialogView.findViewById<Button>(R.id.cancel_button).setOnClickListener { dismiss() }

        return builder.create()
    }

    fun setMyAction(action: () -> Unit) {
        view?.findViewById<MaterialButton>(R.id.proceed_button)?.setOnClickListener { action() }
    }
}

The way I'm calling it from the fragment as this:

btnSubmit.setOnClickListener(view -> {
            MyDialogFragment myDialogFragment = new MyDialogFragment();
            myDialogFragment.show(getChildFragmentManager(), MyDialogFragment.class.getSimpleName());
            myDialogFragment.setMyAction(this::action);
        });

The problem I have here is that it is impossible to call setMyAction from the calling fragment and call the action(), since in the dialog, view is null just like if I try to get it with dialog(). A second problem here is: why is the onCreateView never called, just like onViewCreated?

Thanks in advance!


Solution

  • The problem I have here is that it is impossible to call setMyAction from the calling fragment and call the action(), since in the dialog, view is null just like if I try to get it with dialog().

    The problem that you are experiencing now is that show() is asynchronous. The dialog will be created some time later, not by the time show() has returned.

    The problem that you are not yet experiencing, but will, is that on a configuration change, your activity and its fragment will be recreated by default, and your OnClickListener will be lost.

    Rather than pushing an event handler in, have the DialogFragment expose results (e.g., via a shared ViewModel).

    A second problem here is: why is the onCreateView never called, just like onViewCreated?

    You overrode onCreateDialog(). You cannot both use onCreateDialog() and onCreateView()/onViewCreated(). Pick one and use it.