Kotlin’s extension functions for cleaner code

Maryna Tolok
Appus Studio
Published in
3 min readNov 12, 2021

Kotlin provides an ability to extend a class with new functionality without having to inherit from the class or use design patterns such as Decorator. This is done via special declarations called extensions.

For example, you can write new functions for a class from a third-party library that you can’t modify. Such functions are available for calling in the usual way as if they were methods of the original class. This mechanism is called the extension functions.

To learn more about Kotlin extensions, read the official documentation.

Every big project is a lot of code, and we need it clean and readable. Extension functions can help with it. Let’s dive in and write few extension functions for android development.

  • Control visibility of the view

A very common task in android development is controlling of view visibility state.

fun View.show(){

this.visibility = View.VISIBLE

}

fun View.hide() {

this.visibility = View.INVISIBLE

}

fun View.makeGone() {

this.visibility = View.GONE

}

//Usage

view.show()

view.hide()

view.makeGone()

  • Glide image loading

fun ImageView.glideLoad(url: String) {

Glide.with(this.context).load(url).into(this)

}

//Usage

someImageView.glideLoad(“url”)

  • Validation of string

In every project, we usually work with strings, and nice to have an extension to validate it.

fun String?.valid() : Boolean =

this != null && !this.equals(“null”, true)

&& this.trim().isNotEmpty()

// Usage at call site

if(data.valid())

If your app has registration, login, or email/phone verification you can use an email validation extension or phone formatting extension.

//Email Validation

fun String.isValidEmail(): Boolean

= this.isNotEmpty() && Patterns.EMAIL_ADDRESS.matcher(this).matches()

//Phone number format

fun String.formatPhoneNumber(context: Context, region: String): String? {

val phoneNumberKit = PhoneNumberUtil.createInstance(context)

val number = phoneNumberKit.parse(this, region)

if (!phoneNumberKit.isValidNumber(number))

return null

return phoneNumberKit.format(number, PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL)

}

  • Logging

Logging is very useful in development and debugging of any application. Using class simple name as tag. Each logging level with Throwable and without.

fun Any.debug(message: String) {

Log.d(this::class.java.simpleName, message)

}

fun Any.debug(message: String, tr: Throwable) {

Log.d(this::class.java.simpleName, message, tr)

}

fun Any.error(message: String) {

Log.e(this::class.java.simpleName, message)

}

fun Any.error(message: String, tr: Throwable) {

Log.e(this::class.java.simpleName, message, tr)

}

fun Any.info(message: String) {

Log.i(this::class.java.simpleName, message)

}

fun Any.info(message: String, tr: Throwable) {

Log.i(this::class.java.simpleName, message, tr)

}

fun Any.verbose(message: String) {

Log.v(this::class.java.simpleName, message)

}

fun Any.verbose(message: String, tr: Throwable) {

Log.v(this::class.java.simpleName, message, tr)

}

fun Any.warn(message: String) {

Log.w(this::class.java.simpleName, message)

}

fun Any.warn(message: String, tr: Throwable) {

Log.w(this::class.java.simpleName, message, tr)

}

fun Any.warn(tr: Throwable) {

Log.w(this::class.java.simpleName, tr)

}

fun Any.wtf(message: String) {

Log.wtf(this::class.java.simpleName, message)

}

fun Any.wtf(message: String, tr: Throwable) {

Log.wtf(this::class.java.simpleName, message, tr)

}

fun Any.wtf(tr: Throwable) {

Log.wtf(this::class.java.simpleName, tr)

}

//Usage

debug(“some”)

  • Show Alert Dialog, Toast, or Snackbar

When it comes to UI development, there will be times when you want to show an alert to the user. It might be a toast used for unimportant data or alert dialogs to take confirmations or show some error. Followed extensions can be very useful for these purposes.

// Show alert dialog

fun Context.showAlertDialog(positiveButtonLable : String = getString(R.string.okay),

title : String = getString(R.string.app_name) , message : String,

actionOnPositveButton : () -> Unit) {

val builder = AlertDialog.Builder(this)

.setTitle(title)

.setMessage(message)

.setCancelable(false)

.setPositiveButton(positiveButtonLable) { dialog, id ->

dialog.cancel()

actionOnPositveButton()

}

val alert = builder.create()

alert?.show()

}

// Toash extensions

fun Context.showShotToast(message : String){

Toast.makeText(this, message, Toast.LENGTH_SHORT).show()

}

fun Context.showLongToast(message : String){

Toast.makeText(this, message, Toast.LENGTH_LONG).show()

}

// Snackbar Extensions

fun View.showShotSnackbar(message : String){

Snackbar.make(this, message, Snackbar.LENGTH_SHORT).show()

}

fun View.showLongSnackbar(message : String){

Snackbar.make(this, message, Snackbar.LENGTH_LONG).show()

}

fun View.snackBarWithAction(message : String, actionlable : String,

block : () -> Unit){

Snackbar.make(this, message, Snackbar.LENGTH_LONG)

.setAction(actionlable) {

block()

}

}

// To show an alert dialog in activities, fragments and more

showAlertDialog(mes){

//TODO do on click positive button

}

//To show toast in activities, fragments and more

showShotToast(mes)

showLongToast(mes)

//To show Snackbar applied on any active view

showShotSnackbar(mes)

showLongSnackbar(mes)

snackBarWithAction(mes,title){

//TODO do on action

}

Boilerplate code must be easy to implement and use and Kotlin extension functions can help us do common tasks quickly and get readable code.

--

--