Collection of Kotlin extension functions

joseat

Jose Álvarez

Posted on March 16, 2021

Collection of Kotlin extension functions

This post is about a recopilation of most used extension functions on kotlin for Android Framework.

Event

This utility class is recomended by Google Team to use events in LiveData , is designed for help us to process events, that check if its used or not. Because when a configuration change occurs in the device, the events we are observing may occur when they actually do not.

open class Event<out T>(private val content: T) {

    private var hasBeenHandled = false

    fun getContentIfNotHandled(): T? {
        return if (hasBeenHandled) {
            null
        } else {
            hasBeenHandled = true
            content
        }
    }

}
Enter fullscreen mode Exit fullscreen mode

Now that you know what is used for, you're going to understand the following function.

1. ObserveEvent:

Its very interesting function for the Event class, in particular for LiveData<Event<T>>, whose function is facilitate our work when observing events.

inline fun <T> LiveData<Event<T>>.observeEvent(
        owner: LifecycleOwner, crossinline onEventUnhandledContent: (T) -> Unit) {
    observe(owner, Observer { it.getContentIfNotHandled()?.let(onEventUnhandledContent) })
}
Enter fullscreen mode Exit fullscreen mode

The use is similar when we observe a LiveData from activity or fragment, only instead of call observe method, we must call observeEvent method, passing a lambda as argument.

// Para un LiveData<Event<Int>> it será Int.
viewModel.eventLiveData.observeEvent(this) { doAction(it)}
Enter fullscreen mode Exit fullscreen mode

Fragment

SetToolbarButtonAndTitle

Without a doubt this function should be the most used, because to work with fragment allow us establish the navigation button and the toolbar title easily.

fun Fragment.setToolbarButtonAndTitle(string: String){
    (requireActivity() as AppCompatActivity).supportActionBar?.run {
        setDisplayHomeAsUpEnabled(true)
        title = string
    }
}
Enter fullscreen mode Exit fullscreen mode

Usage:

fun setupViews() {
    setToolbarButtonAndTitle(getString(R.string.fragment_title))
}
Enter fullscreen mode Exit fullscreen mode

Arguments

Obtaining fragment arguments is a bit ugly process, so i bring us a couple of extension fucntions, that makes it easy for us to obtain arguments in fragment.

fun Fragment.extraBoolean(extraId: String, default: Boolean = false)  = lazy { arguments?.getBoolean(extraId, default) ?: default }

fun Fragment.extraInt(extraId: String, default: Int = 0) = lazy { arguments?.getInt(extraId, default) ?: default}

fun Fragment.extraString(extraId: String, default: String = "") = lazy { arguments?.getString(extraId) ?: default }

Enter fullscreen mode Exit fullscreen mode

LiveData

GetValue

One of the biggest inconveniences of using LiveData is obtaining its value, because can return null and we ever check it with Elvis operator.

Now with this couple of functions we haven't worry about of that, only when we want obtain LiveData value we must call her getValue method, passing a default value by params

fun LiveData<Int>.getValue(defaultValue:Int) : Int = value ?: defaultValue

fun LiveData<String>.getValue(defaultValue:String) : String = value ?: defaultValue

fun LiveData<Long>.getValue(defaultValue:Long) : Long = value ?: defaultValue

fun LiveData<Boolean>.getValue(defaultValue:Boolean) : Boolean = value ?: defaultValue
Enter fullscreen mode Exit fullscreen mode

Clearly this is only a example, you can create for more types

Spinner

SetOnItemSelectedListener:

This function is quite useful to set the listener of an adapter and not having to implement all the methods of the AdapterView.OnItemSelectedListener interface, but by using it directly we pass the function to be performed when a Spinner item is selected.

fun Spinner.setOnItemSelectedListener( onNothingSelectedAction: (parent: AdapterView<*>?) -> Unit = {},
        onItemSelectedAction: (parent: AdapterView<*>?, view: View?, position: Int, id: Long) -> Unit) {

    onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
        override fun onNothingSelected(parent: AdapterView<*>?) { onNothingSelectedAction(parent)}

        override fun onItemSelected(parent: AdapterView<*>?, view: View?, 
                                    position: Int, id: Long) {
            onItemSelectedAction(parent, view, position, id)
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Usage:

spinner.setOnItemSelectedListener { _, _, _, _ -> doAction() }
Enter fullscreen mode Exit fullscreen mode

Toast

1. showToast:

This function we save a lot of time to show a toat, making code more readable

  fun Context.toast(message: String, duration: Int = Toast.LENGTH_SHORT) {
        Toast.makeText(this, message, duration).show()
    }
Enter fullscreen mode Exit fullscreen mode

Usage:

toast(getString(R.string.message)
Enter fullscreen mode Exit fullscreen mode

Note: We should keep in mind, that to call this function from fragment we have to call before getContex method.

context.toast(getString(R.string.message))
Enter fullscreen mode Exit fullscreen mode

RecyclerView

1. setOnSwipeListener:

This function allows us to easily set an action for when an element of the RecyclerView is dragged sideways to the left or right (default). Making the code more readable.

fun RecyclerView.setOnSwipeListener( swipeDirs: Int = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT,
        onSwipe: (viewHolder: RecyclerView.ViewHolder, direction: Int) -> Unit =  { _ , _ -> }) {

    val itemTouchHelper = ItemTouchHelper(
        object : ItemTouchHelper.SimpleCallback(0, swipeDirs) {
            override fun onMove(recyclerView: RecyclerView, 
                                viewHolder: RecyclerView.ViewHolder,
                                target: RecyclerView.ViewHolder): Boolean = false

            override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                onSwipe(viewHolder, direction)
            }
    })
    itemTouchHelper.attachToRecyclerView(this)
}
Enter fullscreen mode Exit fullscreen mode

Usage:

recyclerView.setOnSwipeListener { viewHolder, _ -> doAction(viewHolder.currentList[viewHolder.adapterPosition]) }
Enter fullscreen mode Exit fullscreen mode

Intent

requireParcelableExtra

To save us all the checks to obtain an intent, we can use this extension function that does all the checks for us, which receives the id of the extra to extract and will return an Any object.

fun Intent.requireParcelableExtra(extraId:String):Any? {
    if (!hasExtra(extraId))  throw RuntimeException("Intent is not valid, must have  EXTRA_POKEMON")
    return getParcelableExtra(extraId)
}
Enter fullscreen mode Exit fullscreen mode

Usage:

if (result.resultCode == RESULT_OK && intentResult != null) {
    intentResult.requireParcelableExtra(EXTRA_ID) as Int
}
Enter fullscreen mode Exit fullscreen mode

TextView

strikeThrough

With this function we can strike out the TextView text easily.

fun TextView.strikeThrough(strike: Boolean) {
    paintFlags = if (strike) {
        paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
    } else {
        paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
    }
}

Enter fullscreen mode Exit fullscreen mode

Usage:

binding.lblTaskSubject.strikeThrough(isCompleted)
Enter fullscreen mode Exit fullscreen mode

View

GoneUnless

This extension function is very popular and very useful, that's why I think it deserves to be in this compilation. Besides, it is very useful to use it in layouts with dataBinding .

fun View.goneUnless(condition: Boolean) {
    visibility = if (condition) View.VISIBLE else View.GONE
}
Enter fullscreen mode Exit fullscreen mode

Usage:

binding.emptyView.goneUnless(list.isEmpty)
Enter fullscreen mode Exit fullscreen mode

HideKeyboard

It allows to hide the virtual keyboard simply invoking it, we must call it with a view that generally will be an EditText.

fun View.hideKeyboard(): Boolean {
    try {
        val inputMethodManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        return inputMethodManager.hideSoftInputFromWindow(windowToken, 0)
    } catch (ignored: RuntimeException) { }
    return false
}

Enter fullscreen mode Exit fullscreen mode

Usage:

binding.edtName.hideKeyboard()
Enter fullscreen mode Exit fullscreen mode
💖 💪 🙅 🚩
joseat
Jose Álvarez

Posted on March 16, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related