经过初步的学习,在项目中使用了一段时间kotlin后,汇总小组各个成员的心得体会,在此做个记录。
operator关键词 操作符重载
使用举例
```kotlin
val mOnClickCallBack1: (Int) -> Unit =
{ position -> Toast.makeText(this, "position:$position", Toast.LENGTH_LONG).show() }
val mOnClickCallBack2: OnItemClickCallback = object : OnItemClickCallback {
override fun invoke(position: Int) {
Toast.makeText(this@MainActivity, "position:$position", Toast.LENGTH_LONG).show()
}
}
mBtApp.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View?) {
mOnClickCallBack1(1)
mOnClickCallBack1.invoke(1)
mOnClickCallBack2.invoke(1)
//mOnClickCallBack2(1)//想这么使用需要用operator重载 invoke方法
}
})
```
标准函数的使用选择
总结如下:
需要返回本身this 用apply、also
传递this作为参数用apply 传递it用also
不需要返回本身this 用run let with
需要空检查 用run let 不需要空检查用with
传递this作为参数用run with 传递it作为参数用let
成员变量不稳定性
成员变量具有不稳定性,非空判断并不能将其自动转换为非空类型
使用举例
{
mWeather = Weather("25C", "雨", true)
//if (mWeather!=null){
// mWeather.temp
//}
//应如下使用:
mWeather?.temp
}
lateinit Lazy 使用说明
lateinit 就是一个修饰符 被修饰的变量不用做非空校验
Lazy 是一种代理,真正的懒加载对性能有提升
reified 关键词说明
这个单词,也是起的有点犀利,reified 翻译一下就是: 具体化。可以理解为 具体化一个东西。
常用在泛型的具体化
见:package org.jetbrains.anko Intents.kt startActivity
open
使用带open关键词的val对象,来设计基类。可以让这个成员变量又是val类型不可修改,又可以在子类中更改
open val likeDataProvideListener: (() -> CardLikeRequestData)? = null
!!
尽量不要让代码中出现!!强行忽略空判断,大量使用!!的时候需要看一下是否是设计出了问题,该变量是否可以设计成非空类型。
如果实现了java的一个接口,kotlin可能会默认将其中的参数类型设置为可能为空,如果确定在这里不会为空的时候可以直接删除 ?
且不会报错。
多使用闭包
可以使用闭包来代替一些简单的接口
open val likeDataProvideListener: (() -> CardLikeRequestData)? = null
it嵌套
如果有多个 let
函数嵌套的时候,会出现 it
嵌套的情况,这种时候会对当前 it
是什么造成疑惑。这种情况要给后面的 it
修改命名。
扩展函数
Collection和String有大量的扩展函数,使用起来会很方便
Collection 扩展函数
- .forEach 扩展函数,遍历集合
- .isNullOrEmpty 扩展函数,判断集合是null或者为空
- .forEachWithIndex 扩展函数,遍历集合并且可以拿到index
- .lastIndex 扩展属性,最后一个index
String 扩展函数
- .isNullOrBlank 扩展函数,是null或者长度为0或者只有空格
- .isNullOrEmpty 扩展函数,是null或者长度为0
?: return
在执行逻辑的时候,可能会有类似下面这样的代码
// a的类型为A? A中有一个属性b类型为B?
val b :B? = a?.b ?: null
// 此时b的类型为 B?
if (b != null) {
// dosomething
}
这种时候可以替换成
val b :B = a?.b ?: return
// 此时b的类型为 B
// dosomething
让代码更简洁
Kotlin实现Parcelable
方法一:使用注解
1.在gradle中添加
android {
...
//使用Kotlin实验特性
androidExtensions {
experimental = true
}
}
2.使用注解标记数据类并实现Parcelable接口
@Parcelize
data class User(val name: String, val age: Int) : Parcelable
方法二
AS搜索Parcelable Code Generator(for kotlin)插件安装
lambda表达式
1、lambda表达式始终存在于一对{}中,如下:
2、 高阶函数(形参)
高阶函数就是以另一个函数作为参数或返回值的函数
如果用 lambda 来作为高价函数的参数(此时为形参),就必须先了解如何声明一个函数的形参类型,如下:
// printSum 为高阶函数,定义了 lambda 形参
fun printSum(sum:(Int,Int)->Int){
val result = sum(1, 2)
println(result)
}
// 以下 lambda 为实参,传递给高阶函数 printSum
val sum = {x:Int,y:Int->x+y}
printSum(sum)
有了高阶函数,我们可以很轻易地做到一个 lambda 嵌套另一个 lambda 的代码结构
3、大括号放在最后
Kotlin 的 lambda 有个规约:如果 lambda 表达式是函数的最后一个实参,则可以放在括号外面,并且可以省略括号,如:
person.maxBy({ p:Person -> p.age })
// 可以写成
person.maxBy(){
p:Person -> p.age
}
// 更简洁的风格:
person.maxBy{
p:Person -> p.age
}
4、带接收者的 lambda
带接收者的 lambda 丰富了函数声明的信息,当传递该 lambda值时,将携带该接收者,比如:
// 声明接收者
fun kotlinDSL(block:StringBuilder.()->Unit){
block(StringBuilder("Kotlin"))
}
// 调用高阶函数
kotlinDSL {
// 这个 lambda 的接收者类型为StringBuilder
append(" DSL")
println(this)
}
总而言之,lambda 在 Kotlin 和 Kotlin DSL 中扮演着很重要的角色,是实现整洁代码的必备语法糖。