1

MyAlertDialog throws ClassCastException when trying to set the context to the listener. I'm calling the MyAlertDailog from a fragment.

I'm using the guide found in the android dev docs.

https://developer.android.com/guide/topics/ui/dialogs#PassingEvents

MyFragment

class MyFragment : Fragment(), MyAlerDialog.MyAlertDialogListener {

    ...

    fun launchAlertDialog() {
        val dailog = MyAlertDialog().also {
            it.show(requireActivity().supportFragmentManager, "DialogInfoFragment")
        } 
    }

    override fun onDialogPostiveCLick(dialog: DialogFragment) {
        Log.i(TAG, "Listener returns a postive click")
    }
}

MyAlertDialog

class MyAlertDialog : DialogFragment() {
    
    // Use thsi instance for the interface
    internal var listener: MyAlertDialogListener

    // My Fragment implements this interface. 
    interface MyAlertDialogListener {
        onDialogPositiveClick(dialog: DialogFragment)
    }

   
    override fun onAttach(context: Context) {
        super.onAttach(context)
        // Verify  that the host implements the callback. 
        try {
            // My problem is here. 
            listener = context as MyAlertDailog
        } catch (e: ClassCastException) {
            // exception thrown here. 
            throw ClassCastException((context.toString() + " must implement MyAlertDailogListener")
        }
    }

    override fun onCreateDialog(savedInstanceState:Bundle?): Dialog {
        return activity?.let {
             val builder = AlertDialog.builder(it)
             ...
             builder.setPosiviveButton("Positive button",
               DialogInterface.OnClickListener {
                   listener.onDialogPositiveClick(this)     
             }
        }
    }

}

Error report

    java.lang.ClassCastException: com.example.androiddevpractice.MainActivity@ab56136 must implement MyAlertDialogListener
        at com.example.androiddevpractice.topics.userinterface.dialog.MyAlertDialog.onAttach(MyAlertDialog.kt:35)
Shawn
  • 1,222
  • 1
  • 18
  • 41

1 Answers1

1

Even though the launchAlertDialog() method is inside of MyFragment, the "host" for MyAlertDialog is your Activity, not MyFragment.

Implement MyAlerDialog.MyAlertDialogListener inside of MainActivity in order for the cast to succeed. MainActivity can then communicate to MyFragment if it has to.


Alternatively, you could use setTargetFragment() in order to "connect" MyFragment and MyAlertDialog directly:

val dialog = MyAlertDialog()
dialog.setTargetFragment(this, 0)
dialog.show(requireActivity().supportFragmentManager, "DialogInfoFragment")

Then, rather than overriding onAttach() and casting a context, you would cast the results of getTargetFragment():

builder.setPosiviveButton(
        "Positive button",
        DialogInterface.OnClickListener {
            val listener = targetFragment as MyAlertDialogListener
            listener.onDialogPositiveClick(this)     
        }
)
Ben P.
  • 52,661
  • 6
  • 95
  • 123