1

I have Alert Dialog opened from fragment, It have two edittext and one button, one edittext will be visible at a time. On clicking submit, call API -> based on response -> second edittext will be visible. Im using ViewModel and LiveData for listening for response.

Problem: How to correctly observe live data within Alert Dialog context?

 val dialogBinding: DialogTestBinding = DialogTestBinding.inflate(layoutInflater)

        val dialog = AlertDialog.Builder(requireContext()).create()
        dialogBinding.edtMobile.setText(viewModel.userMobile)

        dialogBinding.submit.setOnClickListener {

            if (dialogBinding.edtMobile.visibility == View.VISIBLE) {

                //observing live data with viewLifecycleOwner - how to correctly manage for alert dialog//
                viewModel.newNumber.observe(viewLifecycleOwner) {
                    dialogBinding.edtOtp.visibility = View.VISIBLE
                    dialogBinding.edtMobile.visibility = View.GONE
                    //viewModel.newNumber.removeObservers(viewLifecycleOwner)
                }

                val newNumber = dialogBinding.edtMobile.text.toString()
                callAPI(newNumber, "")

            } else {
                val newNumber = dialogBinding.edtMobile.text.toString()
                val otp = dialogBinding.edtOtp.text.toString()
                callAPI(newNumber, otp)
            }

        }
        dialog.setView(dialogBinding.root)
        dialog.show()

This is working but it will listen for the change even after the AlertDialog is dismissed. Is there any option other than removing the Observer manually?

Mohamed Ashik
  • 332
  • 3
  • 14

1 Answers1

4

For building complex logic within Dialog, use DialogFragment. And the corresponding ViewModel is responsible for storing the LiveData.

class IpAddressEditorDialog : DialogFragment() {
    private lateinit var binding: DialogIpAddressEditorBinding
    private lateinit var viewModel: IpAddressEditorViewModel
    private lateinit var alertDialog: AlertDialog

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        binding = DataBindingUtil.inflate(layoutInflater, R.layout.dialog_ip_address_editor, null, false)
        viewModel = ViewModelProvider(this).get(IpAddressEditorViewModel::class.java)
        alertDialog = getAlertDialog()

        binding.viewModel = viewModel
        binding.lifecycleOwner = this

        return alertDialog
    }

    private fun getAlertDialog(): AlertDialog {
        val dialogBuilder = MaterialAlertDialogBuilder(requireContext()).apply {
            setView(binding.root)

            setPositiveButton(R.string.confirm_label) {
                //do your stuff
            }

            setNegativeButton(R.string.cancel_label) {
                //do your stuff
            }
        }

        return dialogBuilder.create()
    }
}

Demo: https://youtu.be/59s6xa9CNjY

Sam Chen
  • 7,597
  • 2
  • 40
  • 73
  • Are you sure about `this` in `viewModel = ViewModelProvider(this)`? in my oppinion it should be `requireParentFragment()`. Isn't? – C.F.G Jul 28 '23 at 06:26