Collection of Kotlin extension functions
Tags: kotlin, android
Published: 2021-03-16 09:49:40

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. 

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

    private var hasBeenHandled = false

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

}
```

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.

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

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.

```kotlin
// Para un LiveData<Event<Int>> it será Int.
viewModel.eventLiveData.observeEvent(this) { doAction(it)}
```



## 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. 

```kotlin
fun Fragment.setToolbarButtonAndTitle(string: String){
    (requireActivity() as AppCompatActivity).supportActionBar?.run {
        setDisplayHomeAsUpEnabled(true)
        title = string
    }
}
```

Usage:

```kotlin
fun setupViews() {
	setToolbarButtonAndTitle(getString(R.string.fragment_title))
}
```



### 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.

```kotlin
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 }

```





## 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

```kotlin
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
```

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.

```kotlin
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)
        }
    }
}
```

Usage:

```kotlin
spinner.setOnItemSelectedListener { _, _, _, _ -> doAction() }
```



## Toast

### 1. showToast:

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

```kotlin
  fun Context.toast(message: String, duration: Int = Toast.LENGTH_SHORT) {
        Toast.makeText(this, message, duration).show()
    }
```

Usage:

```kotlin
toast(getString(R.string.message)
```

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

```kotlin
context.toast(getString(R.string.message))
```



## 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.

```kotlin
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)
}
```

Usage:

```kotlin
recyclerView.setOnSwipeListener { viewHolder, _ -> doAction(viewHolder.currentList[viewHolder.adapterPosition]) }
```



## 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.

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

Usage:

```kotlin
if (result.resultCode == RESULT_OK && intentResult != null) {
    intentResult.requireParcelableExtra(EXTRA_ID) as Int
}
```



## TextView



### strikeThrough

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

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

```

Usage:

```kotlin
binding.lblTaskSubject.strikeThrough(isCompleted)
```



## 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` . 

```kotlin
fun View.goneUnless(condition: Boolean) {
    visibility = if (condition) View.VISIBLE else View.GONE
}
```

Usage:

```kotlin
binding.emptyView.goneUnless(list.isEmpty)
```



### HideKeyboard

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

```kotlin
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
}

```

Usage:

```kotlin
binding.edtName.hideKeyboard()
```