Dialog Fragment can't pass back events to calling Fragment in Android?

Viewed 1173

In my Android App, I have navigation drawer activity as the MainActivity. And I do not intend to do any tasks in the MainActivity other than navigation, I want to keep it simple and use Fragments for my tasks.

So I have a Fragment which calls a DialogFragment, the DialogFragment passes back events to the Fragment. My implementation is similar to the code given here in the docs.

But, my app crashes when the dialog is needed to appear.

This is my DialogFragment:

class DialogSubjectsProgress: DialogFragment() {
    internal lateinit var listener: TheDialogListener

    interface TheDialogListener {
        fun onDialogCancel(dialog: DialogFragment)
        fun onDialogDismiss(dialog: DialogFragment)
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        listener = context as TheDialogListener
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        super.onCreateDialog(savedInstanceState)

        // show progress dialog
        val progressView = activity!!.layoutInflater.inflate(R.layout.dialog_progress_i, null)
        progressView.findViewById<TextView>(R.id.progress_message).text = "Fetching data"

        return activity!!.let {
            val progressBuilder = AlertDialog.Builder(it, R.style.ThemeOverlay_AppCompat_Dialog)
            progressBuilder
                .setView(progressView)
                .setOnCancelListener {
                    listener.onDialogCancel(this)
                }
                .setOnDismissListener {
                    listener.onDialogDismiss(this)
                }
                .create()
        }
    }
}

And this my Fragment code, which according to the docs is for an Activity:

class FragmentSubjects: Fragment(), DialogSubjectsProgress.TheDialogListener {

    // other code

    private fun addSubject() {
        // show progress dialog
        val progressDialog = DialogSubjectsProgress()
        progressDialog.show(activity!!.supportFragmentManager, "null")

        // todo
        // progressDialog.dismiss()

    }

    override fun onDialogCancel(dialog: DialogFragment) {
        // User canceled the dialog
    }

    override fun onDialogDismiss(dialog: DialogFragment) {
        // Dialog's work is done
        // todo
    }

}

I have found a solution to this here, but I don't really understand it because it is written in Java, and I don't understand Java. I need help in Kotlin!!

----edit----

This is the log:

java.lang.ClassCastException: com.example.kotlinappv3.MainActivity cannot be cast to com.example.kotlinappv3.DialogSubjectsProgress$TheDialogListener
        at com.example.kotlinappv3.DialogSubjectsProgress.onAttach(DialogSubjectsProgress.kt:27)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1404)
        at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
        at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:802)
        at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
        at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
        at androidx.fragment.app.FragmentManagerImpl$1.run(FragmentManager.java:733)
        at android.os.Handler.handleCallback(Handler.java:874)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:198)
        at android.app.ActivityThread.main(ActivityThread.java:6729)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

The line

at com.example.kotlinappv3.DialogSubjectsProgress.onAttach(DialogSubjectsProgress.kt:27)

is pointing to

listener = context as TheDialogListener

in my DialogFragment code.

1 Answers

in your addSubject method instead of

activity!!.supportFragmentManager

use:

childFragmentManager

and in DialogFragment code, change:

override fun onAttach(context: Context) {
    super.onAttach(context)
    listener = context as TheDialogListener
}

to:

override fun onAttachFragment(childFragment: Fragment?) {
    super.onAttachFragment(childFragment)
    listener = context as TheDialogListener
}
Related