Extension function Kotlin


Extension functions were created by Kotlin to simplify the writing of some code, including let, with, run, apply, and ALSO

Let the function

The object can be referred to by it within a function block. Returns the last line of the function block or specifies a return expression

General writing

fun main(a) {
    val text = "RainyJiang"
    println(text.length)
    val result = 1000
    println(result)
}
Copy the code

Let write

fun main(a) {
    val result = "RainyJiang".let {
        println(it.length)
        1000
    }
    println(result)
}
Copy the code

The most common scenario is to use the let function to handle a nullable object

mVideoPlayer? .setVideoView(activity.course_video_view) mVideoPlayer? .setControllerView(activity.course_video_controller_view) mVideoPlayer? .setCurtainView(activity.course_video_curtain_view)Copy the code
mVideoPlayer? .let { it.setVideoView(activity.course_video_view) it.setControllerView(activity.course_video_controller_view) it.setCurtainView(activity.course_video_curtain_view) }Copy the code

Or you need to specify the scope in which a variable can be used

With the function

The previous functions are used slightly differently because they do not exist as extensions. It takes an object as an argument to a function that can be referred to by this within the function block. Returns the last line of the function block or specifies a return expression

Define the Person class

class Person(var name : String, var age : Int)
Copy the code

General writing

fun main(a) {
    var person = Person("RainyJiang".100)
    println(person.name + person.age)
    var result = 1000
    println(result)
}
Copy the code

With writing

fun main(a) {
    var result = with(Person("RainyJiang".100)) {
        println(name + age)
        1000
    }
    println(result)
}
Copy the code

When calling multiple methods of the same class, you can directly call the method of the class, often used in Android RecyclerView onBinderViewHolder, data model attributes mapped to the UI

override fun onBindViewHolder(holder: ViewHolder, position: Int){
    valitem = getItem(position)? :return
    holder.nameView.text = "Name:${item.name}"
    holder.ageView.text = "Age:${item.age}"
}
Copy the code
override fun onBindViewHolder(holder: ViewHolder, position: Int){
    valitem = getItem(position)? :return
    with(item){
        holder.nameView.text = "Name:$name"
        holder.ageView.text = "Age:$age"}}Copy the code

The run function

Actually a combination of the let and with functions, the run function takes a lambda function and returns it as a closure, either the last line of value or the specified return expression

General writing

var person = Person("RainyJiang".100)
println(person.name + "+" + person.age)
var result = 1000
println(result)
Copy the code

The run way

var person = Person("RainyJiang".100)
var result = person.run {
    println("$name + $age")
    1000
}
println(result)
Copy the code

Apply to let,with function any scenario. Since the run function is a combination of the let and with functions, it makes up for the fact that the let function must use it arguments instead of objects in the body of the function. In the run function, it can be omitted like the with function, and directly access the public properties and methods of the instance. On the other hand, it makes up for the null judgment problem of the object passed in to the with function. In the run function, you can do the same thing as the let function. Again, we use the onBindViewHolder case to simplify

override fun onBindViewHolder(holder: ViewHolder, position: Int){
    valitem = getItem(position)? :return
    holder.nameView.text = "Name:${item.name}"
    holder.ageView.text = "Age:${item.age}"
}
Copy the code
override fun onBindViewHolder(holder: ViewHolder, position: Int){
    valitem = getItem(position)? :returnitem? .run { holder.nameView.text ="Name:$name"
        holder.ageView.text = "Age:$age"}}Copy the code

The apply function

Run returns the value of the last line of code as a closure, whereas apply returns the object itself

General writing

val person = Person("RainyJiang".100)
person.name = "ZJX"
person.age = 50
Copy the code

The apply of writing

val person = Person("RainyJiang".100).apply {
    name = "ZJX"
    age = 50
}
Copy the code

The overall function is similar to the run function, except that it returns the value of the object itself, whereas run returns the value of the last row as a closure. Because of that, it works a little differently than the run function. Apply is used when an instance of an object is initialized and attributes in the object need to be assigned. This is also possible when you want to bind data to the View while dynamically producing an XML View, which is very common. In particular, in our development, there will be some data model to View Model instantiation process needs to be used

mRootView = View.inflate(activity, R.layout.example_view, null)
mRootView.tv_cancel.paint.isFakeBoldText = true
mRootView.tv_confirm.paint.isFakeBoldText = true
mRootView.seek_bar.max = 10
mRootView.seek_bar.progress = 0
Copy the code

The code after using the apply function looks like this

// Inflate the XML of a view
mRootView = View.inflate(activity, R.layout.example_view, null).apply {
   tv_cancel.paint.isFakeBoldText = true
   tv_confirm.paint.isFakeBoldText = true
   seek_bar.max = 10
   seek_bar.progress = 0
}
Copy the code

Multilevel empty detection problem

if (mSectionMetaData == null || mSectionMetaData.questionnaire == null || mSectionMetaData.section == null) {
    return;
}
if(mSectionMetaData.questionnaire.userProject ! =null) {
    renderAnalysis();
    return;
}
if(mSectionMetaData.section ! =null && !mSectionMetaData.section.sectionArticles.isEmpty()) {
    fetchQuestionData();
    return;
}
Copy the code

Kotlin’s Apply function is optimized

mSectionMetaData? .apply {// Operate mSectionMetaData when mSectionMetaData is not empty}? .questionnaire? .apply {// Operate the questionnaire when it is not empty}? .section? .apply {// Operate the section when it is not empty}? .sectionArticle? .apply {// Operate sectionArticle when sectionArticle is not empty

}
Copy the code

The braking function

The structure of the also function is actually very similar to that of the let function. The only difference is the return value. Let returns as a closure, returning the value of the last line in the function, or a default value of type Unit if the last line is null. The also function returns the object itself

fun main(a) {
    val result = "RainyJiang".let {
        println(it.length)
        1000
    }
    println(result) // Print: 1000
}
Copy the code
fun main(a) {
    val result = "RainyJiang".also {
        println(it.length)
    }
    println(result) // Print: RainyJiang
}
Copy the code

This applies to any scenario in which a let function is used. The only difference between a let function and a let function is that the value returned by a let function is the value returned by the last line, while the value returned by a also function is the current object. It is generally used for chained calls to multiple extension functions

conclusion

Through the introduction of the above functions, it is convenient to optimize the code writing in Kotlin. On the whole, it seems that the functions of several functions are very similar, but they are different. For example, the run function is a combination of let and with

Finally, attach the test code

class ExpandFunction {


    fun letFunction(a) {
        // The object can be referred to by it within the function
        // Return the last line of the function block or specify a return expression
        /* val text ="HelloWorld" println(text) val result = 1000 println(result) */

        val result = "Hello World".let {
            println(it.length)
            1000
        }
        println(result)
    }

    fun withFunction(a) {
   // When calling multiple methods of the same class, you can use the with function instead of repeating the class name
        var result = with(Person("Jacky".19)) {
            println(name+age)
            1000}}fun runFunction(a) {
        // Combine let and with to apply to any scenario of let and with
        var person = Person("RainyJiang".100)
        var result = person.run {
            println("$name + $age")
            1000
        }
        println(result)
    }

    fun applyFunction(a) {
        // The run function returns the last line of code as a closure, while the apply function returns the object itself
        val person = Person("Jacky".19)
        var result = person.apply {
            name = "tallow"
            age = 18
        }

        // In addition, the apply row number can also be used for hierarchy nulls
    }

    fun alsoFunction(a) {

        // The also function is similar to the let function. Let returns in the form of a closure.
        // Return the value of the last line in the body of the function, or the default value of type Unit if the last line is null. The also function returns the object itself
        val result = "Jacky".also {
            println(it.length)
        }
        println(result)
    }
}

class Person(var name: String, var age: Int)
Copy the code