I know I can call functions from inside MaterialAlertDialogBuilder that uses the user input in the Dialog, but I want to know if there is a way (preferably a good practice) to wait for the user to input the value and the app to execute the proceeding code. I tried it using async .await() with kotlin-coroutines but did not figure it out.
Here's an example of the MaterialAlertDialogBuilder implementation.
val nameInputDialog = MaterialAlertDialogBuilder(requireContext())
val customAlertDialogView = LayoutInflater.from(requireContext())
.inflate(R.layout.dialod_input_et, null, false)
val inputNameDialog: EditText = customAlertDialogView.findViewById(R.id.input_dialog_et)
nameInputDialog.setView(customAlertDialogView)
.setTitle("Type the name")
.setPositiveButton("Accept") { dialog, _ ->
val nameToInput = inputNameDialog.text.toString()
if (nameToInput == "") {
Toast.makeText(requireContext(), "Type a name", Toast.LENGTH_SHORT)
.show()
makeDialogBoxAndSetGroupID()
} else if (nameToInput != "") {
GlobalScope.launch() {
nameToDisplay = async {
nameToInput
}
}
dialog.dismiss()
}
}
.setNegativeButton("Cancel") { dialog, _ ->
dialog.dismiss()
}.show()
CodePudding user response:
What exactly do you need to wait for?
If you have a dialog with an EditText, and you want to ensure the dialog stays open until the user types something that you consider valid, then you need to delegate all this validation, keep a reference to your dialog, and act accordingly once your ViewModel responds.
In short.
Fragment/Activity
: Creates a Dialog and holds a reference.
val nameInputDialog = ... show()
Inside the onPositiveButton
:
val nameToInput = inputNameDialog.text.toString()
viewModel.inputNameChanged(nameToInput)
In your ViewModel:
fun inputNameChanged(name: String) {
//validate (preferably delegate to a validator/useCase so you can UT it)
if (validator.isValid(name)) {
_uiState.postValue(YourSealedClass.Valid(name))
} else {
_uiState.postValue(YourSealedClass.Empty())//for e.g.
}
}
And back in your Fragment/Activity where you observe this...
viewModel.uiState.observe(viewLifecycleOwner, Observer { state ->
when(state) {
is YourSealedClass.Valid -> dialog.dismiss()
is YourSealedClass.Empty -> {
Toast.makeText(...).show() //a toast is bad for this, but it works.
}
}
And this is how Google recommends you work in a "reactive" way.