一手遮天 Android - kotlin: Lambda 表达式,高阶函数
示例如下:
/kotlin/Demo10.kt
/**
* 本例用于演示 Lambda 表达式,高阶函数
*/
package com.webabcd.androiddemo.kotlin
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Toast
import com.webabcd.androiddemo.R
import kotlinx.android.synthetic.main.activity_kotlin_demo10.*
class Demo10 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_kotlin_demo10)
sample1()
sample2()
sample3()
}
fun sample1() {
// 传统方式监听按钮的点击事件
button1.setOnClickListener(object: View.OnClickListener{
override fun onClick(v: View?) {
// 这里的 this@Demo10 相当于 java 中的 Demo10.this
Toast.makeText(this@Demo10, "button1 clicked", Toast.LENGTH_SHORT).show()
}
})
// lambda 方式监听按钮的点击事件
button2.setOnClickListener {
// 这里的 this 指向的就是 activity
Toast.makeText(this, "button2 clicked", Toast.LENGTH_SHORT).show()
}
}
fun sample2() {
fun1() // fun1
appendMessage(fun2()) // fun2
appendMessage(fun3()) // fun3
appendMessage("${fun4(1, 2)}") // 3
appendMessage("${fun5(1, 2)}") // 3
appendMessage("${fun6(1, 2)}") // 2
}
// 无传入参数,无返回值的 lambda
val fun1 = { appendMessage("fun1") }
// 无传入参数,有返回值的 lambda(自动推断返回值的类型)
val fun2 = { "fun2" }
// 无传入参数,有返回值的 lambda(这里的 () -> String 代表无传入参数,返回值的类型是 String)
val fun3: () -> String = { "fun3" }
// 有传入参数,有返回值的 lambda(自动推断返回值的类型)
// 这里的 -> 的左边是参数声明,右边是表达式
val fun4 = { a: Int, b: Int -> a + b }
// 有传入参数,有返回值的 lambda
// 这里 (Int, Int) -> Int 的意思是有 2 个 Int 类型的传入参数,返回值是 Int 类型的(如果没有返回值,则这里写 -> Unit 即可)
// 这里 { a, b -> a + b } 的意思是 -> 的左边是参数声明,右边是表达式
val fun5: (Int, Int) -> Int = { a, b -> a + b }
// 这里有个约定,如果你后面的表达式用不到某个参数,就用 _ 表示这个参数
val fun6: (Int, Int) -> Int = { _ , b -> b }
// 演示高阶函数(High-Order Function),所谓高阶函数就是将函数用作另一个函数的传入参数或返回值
fun sample3() {
// lambda 表达式作为函数的传入参数的示例
// 下面 2 种写法均可,但是建议用第 2 种
appendMessage("${funA(1,2, { a, b -> a + b })}") // 3
appendMessage("${funA(1,2) { a, b -> a + b }}") // 3
// lambda 表达式作为函数的传入参数的示例
// 以下面的例子为例,当 lambda 表达式只有一个参数时,可以用简便写法,通过 it 替代 x -> x
appendMessage("${funB(3) { x -> x > 5 }}") // 0
appendMessage("${funB(10) { it > 5 }}") // 10
// lambda 表达式作为函数的返回值的示例
appendMessage("${funC(10)(1, 2)}") // 13
// lambda 表达式实现扩展方法的示例
appendMessage("${"abc".sumASCII { it.toInt() }}") // 会输出 294(就是 97 + 98 + 99)
}
// lambda 表达式作为函数的传入参数的示例
// 这里有个建议的命名规范(operation - 多个传入参数;selector - 一个传入参数且返回值不是 bool 类型;predicate - 一个传入参数且返回值为 bool 类型)
fun funA(a: Int, b: Int, operation: (Int, Int) -> Int) : Int {
return operation(a ,b)
}
// lambda 表达式作为函数的传入参数的示例
// 这里有个建议的命名规范(operation - 多个传入参数;selector - 一个传入参数且返回值不是 bool 类型;predicate - 一个传入参数且返回值为 bool 类型)
fun funB(a: Int, predicate: (Int) -> Boolean) : Int {
return if (predicate(a)) {
a
} else {
0
}
}
// lambda 表达式作为函数的返回值的示例
fun funC(a: Int): (Int, Int) -> Int {
return fun(x, y) : Int {
return a + x + y
}
}
// lambda 表达式实现扩展方法
// 这里有个建议的命名规范(operation - 多个传入参数;selector - 一个传入参数且返回值不是 bool 类型;predicate - 一个传入参数且返回值为 bool 类型)
fun CharSequence.sumASCII(selector: (Char) -> Int): Int {
var sum: Int = 0
for (element in this) {
sum += selector(element)
}
return sum
}
fun appendMessage(message: String) {
textView1.append(message)
textView1.append("
")
}
}
/layout/activity_kotlin_demo10.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="传统方式监听按钮的点击事件"/>
<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="lambda 方式监听按钮的点击事件"/>
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>