I want to display an error dialog while receiving errors in any destination fragment's ViewModel
.
Now, I created a BaseViewModel
and a BaseFragment
that does the stuff, and make all fragments
and ViewModels
extend it.
But it's hard to connect all destinations to the dialog's DialogFragment.
Should I leave the dialog out of the nav_graph.xml
?
If you are using kotlin you can do it by using an extension function
inline fun Activity.alertDialog(
title: CharSequence? = null,
message: CharSequence? = null,
func: AlertDialogHelper.() -> Unit
) {
val dialogFragment = AlertDialogHelper(this, title, message).apply {
func()
}
val fragmentTransaction = (this as AppCompatActivity).supportFragmentManager.beginTransaction()
fragmentTransaction.let { dialogFragment.show(it, TAG) }
}
inline fun Fragment.alertDialog(
title: CharSequence? = null,
message: CharSequence? = null,
func: AlertDialogHelper.() -> Unit
) {
val dialogFragment = AlertDialogHelper(this.context!!, title, message).apply {
func()
}
val fragmentTransaction = (this).childFragmentManager.beginTransaction()
fragmentTransaction.let { dialogFragment.show(it, TAG) }
}
AlertDialogHelper
is the same dialog class that is extended by DialogFragment
AlertDialogHelper
class AlertDialogHelper(context: Context, title: CharSequence?, message: CharSequence?) :
DialogFragment() {
private val dialogView: View by lazyFast {
LayoutInflater.from(context).inflate(R.layout.dialog_layout, null)
}
private val title: TextView by lazyFast {
dialogView.findViewById(R.id.dialogInfoTitleTextView)
}
private val message: TextView by lazyFast {
dialogView.findViewById(R.id.dialogInfoMessageTextView)
}
private val positiveButton: Button by lazyFast {
dialogView.findViewById(R.id.dialogInfoPositiveButton)
}
private val negativeButton: Button by lazyFast {
dialogView.findViewById(R.id.dialogInfoNegativeButton)
}
var cancelable: Boolean? = true
init {
this.title.text = title
this.message.text = message
}
fun positiveButton(text: CharSequence, func: (() -> Unit)? = null) {
with(positiveButton) {
this.text = text
setClickListenerToDialogButton(func)
}
}
fun negativeButton(text: CharSequence, func: (() -> Unit)? = null) {
with(negativeButton) {
this.text = text
setClickListenerToDialogButton(func)
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return dialogView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
title.goneIfTextEmpty()
message.goneIfTextEmpty()
positiveButton.goneIfTextEmpty()
negativeButton.goneIfTextEmpty()
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
isCancelable = this.cancelable!!
}
override fun onDestroyView() {
super.onDestroyView()
}
private fun TextView.goneIfTextEmpty() {
visibility = if (text.isNullOrEmpty()) {
View.GONE
} else {
View.VISIBLE
}
}
private fun Button.setClickListenerToDialogButton(func: (() -> Unit)?) {
setOnClickListener {
func?.invoke()
dialog?.dismiss()
}
}
fun <T> lazyFast(operation: () -> T): Lazy<T> = lazy(LazyThreadSafetyMode.NONE) {
operation()
}
}