One of Kotlin’s strengths is its extension functions, which can be used wisely to make your code more elegant and smooth to read. Here are some of the inline extension functions that are often used in development. With, run, apply, and so on, how to use these functions and where to use them. My advice is to remember what each function does. What is the return value? Keep these two points in mind and then you will be able to use them proficiently according to the actual development scenario. In fact, these functions are very similar, and different functions can accomplish the same function, as shown in the following example. In my previous development experience, these functions are mainly used in two scenarios, one is non-null judgment, the other is the initialization of the object or the frequent invocation of itself and methods.

1. with

Fun <T, R> with(Receiver: T, block: T.() -> R): R

Function: Takes an object as an argument to a function. Within a function, the object can be referred to by this. The return value is the last line of the function or a return expression.

Example: 1. A lot of times in a custom view when we initialize a brush we write the following code

Var paint = paint () paint.color = color.black paint.strokeWidth = 1.0f paint.textSize = 18.0f paint.isantiAlias = trueCopy the code

If you use with, you can write it like this

Var paint = paint () with(paint) {color = color.black strokeWidth = 1.0f textSize = 18.0f isAntiAlias = true} var paint = paint () with(paint) {color = color.black strokeWidth = 1.0f textSize = 18.0f isAntiAlias = true}Copy the code

It feels more natural to write without paint.

    var list= mutableListOf<String>()
    list.add("1")
    list.add("2")
    list.add("3")
Copy the code

With can be written as

var list = with(mutableListOf<String>()) {
        add("1")
        add("2")
        add("3")
        this
    }
Copy the code

There are many scenarios in development where the with feature can be used, and understanding it will allow you to use it flexibly.

2. TakeIf and takeUnless

takeif

Definition: fun t.akeif (predicate: (T) -> Boolean): T?

Function: passes a function argument, returns T object if the function result is true, otherwise returns NULL.

Example: When using File files, it is common to determine whether File exists, for example

   var file = File("filePath")
    if (file.exists()) {
        //do something
    } else {
        return false
    }
Copy the code

After using takeif

var file = File("filePath").takeIf { it.exists() }? :return false //do somethingCopy the code

takeUnless

Definition: fun t.akeunless (predicate: (T) -> Boolean): T?

Function: In contrast to takeIf, the argument function returns a T object if it returns false, or null otherwise.

3. run

Definition:

(1) the fun run block: () – > (R) : R (2) fun < T, R > T.r UN (block: t. () – > R) : R

Run returns the last line of the function, or a return expression.

Example: Return the last line

kotlin.run {
    println("11")
    println("22")
}
Copy the code

Results:

I/System.out: 11

I/System.out: 22

Returns a return expression, the code after the return is not executed (note @run)

kotlin.run {
        return@run println("11")
        println("22")
    }
Copy the code

Result: I/ system. out: 11

4. repeat

Fun repeat(times: Int, action: (Int) -> Unit)

Run the action function times repeatedly, times starting from 0

Example: Similar to the for loop function, for example

repeat(5){ println("count:$it") }
Copy the code

Is equivalent to

for (i in 0.. 4) { println("count:$i") }Copy the code

or

(0.. 4).forEach{println("count:$it")}Copy the code

5. let

Fun <T, R> t. et(block: (T) -> R): R

Function: Call the let function of the object (T), then the object is the parameter of the function. The object can be referred to by it within a function. Returns the last line of the function or specifies a return expression.

Example: Somewhat like run(),let can be used for null-safe validation in use, variable? . Let {} for example

Val data =... data? . Let {... // If data is not null, the code will execute here}Copy the code

6. apply

Fun t.ply (block: t. () -> Unit): T

Function: call the apply function of the object, within the scope of the function, you can call any method of the object, and return the object.

Example:

var list = mutableListOf<Int>().apply {
    add(1)
    add(2)
    add(3)
}
Copy the code

Note the difference between run and apply. Run returns the last line, and apply returns the object itself. We can see from the definition of apply that apply applies to objects that need to assign values to their attributes when they are initialized. Let’s do the paintbrush example

The original

Var paint = paint () paint.textSize = 14.0f paint.color = color.white paint.isantiAlias = falseCopy the code

After using the apply

Var paint = paint ().apply {textSize = 14.0f color = color.white isAntiAlias = false} var paint = paint ().apply {textSize = 14.0f color = color.white isAntiAlias = false}Copy the code

And since the apply function returns its object itself, it can work with? Complete multiple levels of non-null judgment operations, or in Builder mode

7. also

Definition: fun t.also (block: (T) -> Unit): T

Function: Calls the object’s also function, which can refer to the object by IT within the function block and returns the object itself. (Note the difference from let, which returns the last line and also returns the object itself.)

Example: Cases where you need to return the object itself (this), such as builder pattern.