怎样制作自己公司的网站湖北工程建设招投标中心网站
Kotlin是一门非常方便的开发语言,它的语法糖有很多,要想要很熟练的掌握kotlin语言,只有不断地使用kotlin写代码,从而达到量到质的一个改变。本文也只是介绍其中的一点内容,内容很松散,有些知识点需要自己动手去写,去实现才能真正体会其中的魅力。
1 高阶函数
1.1 Lambda表达式
分析高阶函数的基础是lambda表达式,先看一下常见的Lambda表达式的使用方式。
fun main() {// () -> Unit 空参函数 并且 没有返回值 函数名=method01// TODO 定义没有问题,调用不行/*var method01 : () -> Unitmethod01() // 不能调用 没有具体的实现var method02 : (Int, Int) -> Intmethod02(9, 9)var method03: (String, Double) -> Any?method03("Derry", 543354.4)var method04 : (Int, Double, Long, String ? ) -> Booleanmethod04(1, 545, 3543, null)var method05 : (Int, Int) -> Intmethod05(9, 9)*/// : (形参类型)// = {具体详情}// TODO 定义没有问题,调用OK ,因为有实现了var m06 : (Int, Int) -> Int = {number1, number2 -> number1 + number2}println("m06:${m06(9, 9)}")var m07 = { number1: Int , number2: Int -> number1.toDouble() + number2.toDouble()}println("m07:${m07(100, 100)}")var m08 : (String, String) -> Unit = {aString, bString -> println("a:$aString, b:$bString")}m08("李元霸", "王五")var m09 : (String) -> String = {str -> str}println("m09:${m09("降龙十八掌")}")var m10 : (Int) -> Unit = {when(it) {1 -> println("你是一")in 20..30 -> println("你是 二十 到 三十")else -> println("其他的数字")}}m10(29)var m11 : (Int, Int, Int) -> Unit = { n1, n2, n3 ->println("n1:$n1, n2:$n2, n3:$n3")}m11(29,22,33)var m12 = { println("我就是m12函数,我就是我") }m12()val m13 = {sex: Char -> if (sex == 'M') "代表是男的" else "代表是女的"}println("m13:${m13('M')}")// 覆盖操作var m14 = {number: Int -> println("我就是m14 我的值: $number")}m14 = {println("覆盖 我的值: $it")}m14(99)// 需求:我想打印, 并且,我还想返回值,就是 我什么都想要var m15 = { number: Int -> println("我想打印: $number")number + 1000000}println("m15:${m15(88)}")
}
代码中的注释有对应的解释,此处我们不做过多的赘述,上面一共展示了15中Lambda表达式的使用方式,其实总结下来就2种形式:
// : (形参类型)
// = {具体详情}
对于Lambda表达式,至于说到底什么是Lambda表达式,其实我理解他就是一种规则,允许在编程过程中使用的一种规则。说穿了没有什么高深的东西,就是多多练习使用后熟能生巧的一个过程,这里只介绍这种语法糖即可。
1.2 扩展函数
fun main() {val stu = Student()stu.add(100, 200)// KT本来就有val file = File("///")file.readText()file.show()
}// 扩展 函数
fun Student.add(n1: Int, n2: Int) {println("结果:${n1 + n2}")
}fun Student.show() {println("Student show")
}// 给 java File 增加 扩展函数
fun File.show() {println("给 java File 增加 扩展函数")
}
扩展函数可以理解为在外部对已有的类添加函数,什么意思呢,说穿了就是不想改动原来的类,但是呢又想对类的功能进行扩展,保持了原有的实现,然后又扩展了一项功能,使得其他的该类的变量都能够进行使用,这就是扩展函数的核心。
1.3 高阶函数
高阶函数的理解:如果在函数上用到了Lambda表达式,那该函数就属于高阶函数。
fun main() {show(true) {// println(it)'M'}
}// TODO loginMethod:(Boolean)->Unitfun loginMethod(b: Boolean) : Unit {}// loginMethod 方法名
// (Boolean)方法的那个括号
// -> 方法体 干活
// Unit == voidfun show(isLogin: Boolean, loginMethod:(Boolean)->Char) {if (isLogin) {println("登录成功")val r = loginMethod(true)println(r)} else {println("登录失败")loginMethod(false)}
}
上面简单的举了一个扩展函数的例子,具体的解释代码中已经注释了,其实高阶函数,就是在参数中定义了一个Lambda表达式。
其实我们平时使用的let、run、with、apply、also都是一些高阶的扩展函数,我们来分析一下具体的实现,感受一下高阶函数的魅力:
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}block(this)return this
}@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {contract {callsInPlace(block, Invoc ationKind.EXACTLY_ONCE)}return block(this)
}@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}block()return this
}@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}return receiver.block()
}@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}return block()
}
总结:
also let :
使用的参数传递调用者对象的方式,也就是将调用者的对象以参数的形式传入到高阶函数中,然后通过"调用者对象参数.方法"的方式调用调用者对象中的方法。
返回值不一样,also的返回值是调用者对象本身,let的返回值是高阶函数实现体的最后一行代码的返回值类型。
apply、with、run:
都是通过对调用者对象增加匿名函数的方式实现,这样做的好处是在高阶函数的具体实现中全局的增加了一个this对象,随时都可以直接调用调用者对象中的其他方法,不需要使用"this.方法"的方式。
返回值不一样,apply返回的是调用者本身,with run返回的是高阶函数的最后一行代码的返回类型。
1.4 Kt关键字in out
此处多提一下,kotlin中有2个关键字:in和out,其实这2个关键字比较好理解,只要你理解了之前分析的泛型中的extend和super关键词,那么我们肯定就能理解,来看一下Java中泛型的读取模式:
// 泛型读取模式void test01() {// ? extends FuClass == 只能获取,不能修改List<? extends FuClass> list = new ArrayList<ZiClass>();// 不能修改/*list.add(fuClass);list.add(ziClass);*/// 能获取FuClass fuClass = list.get(0);// TODO =============================================// ? super ZiClass == 只能修改,不能获取List<? super ZiClass> list2 = new ArrayList<FuClass>();// 能添加list2.add(ziClass);// 不能获取// ZiClass ziClass = list2.get(0);}
extend是只能获取不能修改,super是只能修改不能获取。那么kotlin中extend对应的out,super对应的in。
fun test01() {// out 只能取,不能修改 == ? extends FuClassval list: MutableList<out FuClass> = ArrayList<ZiClass>()// in 只能修改(存), 不能获取 === ? super ZiClassval list2: MutableList<in ZiClass> = ArrayList<FuClass>()
}
// 这个类,就是只能获取,不能修改了
// 声明的时候加入 一劳永逸了<in T>
class Worker <out T> {// 能获取fun getData() : T? = null// 不能修改/*fun setData(data: T) {}fun addData(data: T) {}*/
}
// 这个类,就是只能修改, 不能获取
// 声明的时候加入 一劳永逸了<in T>
class Student<in T> {/*fun a(list: MutableList<in T>) {}fun a2(list: MutableList<in T>) {}fun a3(list: MutableList<in T>) {}fun a4(list: MutableList<in T>) {}fun a5(list: MutableList<in T>) {}*/fun setData(data: T) {}fun addData(data: T) {}// 不能获取// fun getData() : T
}
2 协程
2.1 协程的使用
协程的使用主要是2个方式runBlocking和GlobalScope.launch的方式,具体看一下实现
fun click3(view: View) = runBlocking {// TODO 完成这种 异步线程 和 主线程 的切换, 这个需求:之前我们用RxJava实现过了哦// 1.注册耗时操作// 2.注册耗时操作完成后,更新注册UI// 3.登录耗时操作// 4.登录耗时操作完成后,更新登录UI// mainlaunch {val pro = ProgressDialog(this@MainActivity)pro.setMessage("正在执行中...")pro.show()withContext(Dispatchers.IO) {// 1.注册耗时操作 异步Log.d("click3", "1.注册耗时操作: ${Thread.currentThread().name}")Thread.sleep(2000)}// 2.注册耗时操作完成后,更新注册UI mainLog.d("click3", "2.注册耗时操作完成后,更新注册UI: ${Thread.currentThread().name}")withContext(Dispatchers.IO) {// 3.登录耗时操作 异步Log.d("click3", "3.登录耗时操作: ${Thread.currentThread().name}")Thread.sleep(3000)}// 4.登录耗时操作完成后,更新登录UILog.d("click3", "4.登录耗时操作完成后,更新登录UI: ${Thread.currentThread().name}")// pro.dismiss()}}
runBlocking平时的开发中一般是不用的,一般是在测试过程中使用,因为runBlocking是阻塞式的。
// 非阻塞
fun click4(view: View) {// TODO 完成这种 异步线程 和 主线程 的切换, 这个需求:之前我们用RxJava实现过了哦// 1.注册耗时操作// 2.注册耗时操作完成后,更新注册UI// 3.登录耗时操作// 4.登录耗时操作完成后,更新登录UI// mainGlobalScope.launch (Dispatchers.Main) {val pro = ProgressDialog(this@MainActivity)pro.setMessage("正在执行中...")pro.show()withContext(Dispatchers.IO) {// 1.注册耗时操作 异步Log.d("click3", "1.注册耗时操作: ${Thread.currentThread().name}")Thread.sleep(2000)}// 2.注册耗时操作完成后,更新注册UI mainLog.d("click3", "2.注册耗时操作完成后,更新注册UI: ${Thread.currentThread().name}")textView.text = "注册成功,你可以去登录了"pro.setMessage(textView.text.toString())withContext(Dispatchers.IO) {// 3.登录耗时操作 异步Log.d("click3", "3.登录耗时操作: ${Thread.currentThread().name}")Thread.sleep(3000)}// 4.登录耗时操作完成后,更新登录UILog.d("click3", "4.登录耗时操作完成后,更新登录UI: ${Thread.currentThread().name}")textView.text = "登录成功,欢迎回来"pro.setMessage(textView.text.toString())pro.dismiss()}}
2.2 协程的原理
至于原理,有一篇博客讲解的很好,大家可以参考:https://www.jianshu.com/u/a324daa6fa19