Manageable Dialogs in Android

Why are dialogs so difficult?

Using Dialogs in Android has always been a bit of a pain. In our apps, we tend to have various kinds for different things resulting in tons of lines of code for such a simple purpose. When we need the user to know about something in our app or that an error occurred we show an AlertDialog. For business decisions it may require that a network request needs to block the user from doing anything but wait, so we show a ProgressDialog (now deprecated). Additionally, if we need to request permission for something dangerous (i.e. versionCodes >= 21) we do that. And then in more complex cases we ask the user something and have them perform an action by pressing one of three buttons (positive, neutral, negative), provide a list of options either single choice or multiple, or even collect input from the user. As you could imagine (or may have experienced before) this can lead to tons of the same code doing slightly different things littered throughout your codebase.

This can become a real problem when we need to update certain aspects of the dialogs within our application such as the theme or maybe we were previously using cancelable dialogs and now we want them to not be cancellable. This could become a large task consuming valuable time! As creative engineers and proponents of object-oriented programming, however, we have managed to get around this by introducing our own version of boilerplate to solve these problems using static methods within a utility class. This can make these changes much easier and provide a reusable set of methods for other projects.

For example, the following DialogUtil.java class has multiple ways of showing dialogs in java using this pattern:

So great! Now we have a utility class we can leverage for any project in which we need to display dialogs. It is easy to make any changes in this utility class if we need to update our apps dialogs preventing us from having to open various files to update each dialog one by one. Although this isn’t perfect it is much better than the alternative. Using this utility class we can show a dialog like so:

The alternative without that wrapper class shows why it is more preferable to wrap the methods:

Could you imagine searching for this code in your project and changing R.style.AppTheme_Dialog to something else for every instance (of course we could use find & replace with modern IDEs…), rather than opening the utility class and updating a single place?! (I can’t!) However, we choose to wrap the functionality using Java doesn’t matter too much because, with the introduction of Kotlin, we now have a better way to incorporate dialogs into our codebase with much less boilerplate.

A better approach with Kotlin

The Kotlin programming language treats functions as first-class citizens. From the Kotlin docs:

Kotlin functions are first-class, which means that they can be stored in variables and data structures, passed as arguments to and returned from other higher-order functions. You can operate with functions in any way that is possible for other non-function values.

But what does this mean for Dialogs?

Well, instead of including listeners within our activities or directly in our DialogUtils class (see above) we can just pass a function as a parameter to one of our utility functions in Kotlin making our code even more readable.

With a custom extension function on the Context class, we can create the same Dialog with a list and a single choice option style using the sample from Util.kt :

and then its usage from MainActivity.kt:

The best part is we can now use any class that inherits from Context and this displaySingleChoiceDialog method is available to us!

Or if you like the popular library Anko you can do the same thing:

Don’t forget to add the following dependencies to your build.gradle file if you like Anko better:

Summary

Working with dialogs in Kotlin is much easier than doing the same in java. Since functions in Kotlin are first class we can move all the boilerplate for our dialogs into a common utility file and then use lambdas to handle the actions performed on the dialogs within our activities.

NOTE: with Kotlin’s null safety we could extend a single function in a utility file to handle the building of any dialog we want!

If you enjoyed this article or have a comment about an error please leave a comment.

Also, don’t be a stranger and follow me on social media!