10 Useful Kotlin Extension Functions for Simplifying Your Code

Summit Kumar
3 min readApr 8, 2023

--

Kotlin is a powerful programming language that provides much functionality out of the box. However, Kotlin’s true power lies in its extension functions, which allow developers to add functionality to existing classes and objects without subclassing or modifying their source code. Here are 10 useful Kotlin extensions that make your code more concise and readable.

Here are the 10 Kotlin extension function I regularly use in my projects and suggest every Android developer must use to simplify their code.

withNotNull —
One common problem that developers encounter when working with nullable values is checking for null before performing operations. The withNotNull extension function simplifies this process by allowing developers to execute a block of code only if the value is not null.

inline fun <T : Any, R> T?.withNotNull(block: (T) -> R): R? {
return this?.let(block)
}

Usages: —

val nullableValue: String? = null
nullableValue.withNotNull { value ->
// Code here will only be executed if nullableValue is not null
}

toLiveData —
LiveData is a data holder class that is lifecycle-aware and can be observed for changes. The toLiveData extension function simplifies the process of converting a Flow into a LiveData.

fun <T> Flow<T>.toLiveData(): LiveData<T> {
return liveData {
collect {
emit(it)
}
}
}

Usage: —

val flow = flowOf("Hello", "World")
val liveData = flow.toLiveData()

notEmpty —
The notEmpty extension function simplifies the process of checking if a collection is not empty.

fun <T> Collection<T>?.notEmpty(): Boolean {
return this != null && this.isNotEmpty()
}

More concise way — Thank you @richard.green_70881 for pointing it out

fun <T> Collection<T>?.notEmpty(): Boolean {
return this?.isNotEmpty() == true
}

Usage: —

val list: List<Int> = emptyList()
if (list.notEmpty()) {
// Code here will only be executed if list is not empty
}

getOrThrow
The getOrThrow extension function simplifies the process of getting a value from a map and throwing an exception if the key is not found.

fun <K, V> Map<K, V>.getOrThrow(key: K): V {
return this[key] ?: throw NoSuchElementException("Key $key not found in map")
}

Usage: —

val map = mapOf("key1" to "value1", "key2" to "value2")
val value = map.getOrThrow("key3")

toFormattedString —
The toFormattedString extension function simplifies the process of formatting numbers and dates.

fun Int.toFormattedString(): String {
return NumberFormat.getInstance().format(this)
}

fun Long.toFormattedString(): String {
return NumberFormat.getInstance().format(this)
}

fun Date.toFormattedString(): String {
return SimpleDateFormat.getDateInstance().format(this)
}

Usage: —

val number = 1000000
val formattedNumber = number.toFormattedString()

debounce —
The debounce extension function simplifies the process of delaying the execution of a block of code until a specified amount of time has passed since the last time the block was executed.

fun View.onClick(debounceDuration: Long = 300L, action: (View) -> Unit) {
setOnClickListener(DebouncedOnClickListener(debounceDuration) {
action(it)
})
}

private class DebouncedOnClickListener(
private val debounceDuration: Long,
private val clickAction: (View) -> Unit
) : View.OnClickListener {

private var lastClickTime: Long = 0

override fun onClick(v: View) {
val now = SystemClock.elapsedRealtime()
if (now - lastClickTime >= debounceDuration) {
lastClickTime = now
clickAction(v)
}
}
}

Usage: —

button.onClick(debounceDuration = 500L) {
// Code here will only be executed if 500 milliseconds have passed since the last click
}

toBitmap —
The toBitmap extension function simplifies the process of converting a drawable to a bitmap.

fun Drawable.toBitmap(): Bitmap {
if (this is BitmapDrawable) {
return bitmap
}

val bitmap = Bitmap.createBitmap(intrinsicWidth, intrinsicHeight, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
setBounds(0, 0, canvas.width, canvas.height)
draw(canvas)

return bitmap
}

Usage: —

val drawable = ContextCompat.getDrawable(context, R.drawable.my_drawable)
val bitmap = drawable.toBitmap()

toUri —
The toUri extension function simplifies the process of converting a file path to a Uri.

fun String.toUri(): Uri {
return Uri.parse(this)
}

Usage: —

val filePath = "/storage/emulated/0/Download/my_file.pdf"
val fileUri = filePath.toUri()

applyIf —
The applyIf extension function simplifies the process of applying a block of code to an object only if a condition is met.

inline fun <T> T.applyIf(condition: Boolean, block: T.() -> Unit): T {
return if (condition) {
this.apply(block)
} else {
this
}
}

Usage: —

val number = 5
val formattedNumber = number.applyIf(number > 10) {
toFormattedString()
}

In conclusion, Kotlin extension functions can be a powerful tool for simplifying code and making it more readable. By leveraging these 10 useful extensions, you can make your code more concise, efficient, and maintainable.

--

--

Summit Kumar

Tech-savvy BTech IT professional with a passion for latest technologies. Always seeking new challenges & opportunities to expand my knowledge. #KeepLearning #IT