Kotlin相关的一些实用方法与技巧

这里用于搜集记录一些Kotlin相关的一些实用小技巧
后续会不断增加
目前加入的有:

  • Kotlin 自定义 Getters/Setters
  • 给 Getters/Setters 加访问权限
  • Kotlin延迟加载,加快程序启动时间
  • 使用Data Classes(数据类)少写代码
  • Object Expressions(对象表达式)
  • Companion Object(伴生对象)
  • Optional Parameters(可选参数)
  • (noarg)data class 加无参构造 (allopen)去final

Kotlin 自定义 Getters/Setters

  • 在特殊情况下,我们需要自己操作get set,操作如下:
    1
    2
    3
    4
    5
    6
    7
    class Book {
    var name: String
    get() = field //注:看下面注解释
    set(value){// set
    field = "name =" + value//注:这里不能直接使用name,在kotlin中会导致循环调用。因为属性的调用也是对get的调用,因此会产生递归,造成内存溢出。
    }
    }

给 Getters/Setters 加访问权限

1
2
3
var name: String = ""
private set
//private get //注意: 编译错误,get的访问权限和属性一致

Lazy Kotlin延迟加载,加快程序启动时间

  • 为什么说lazy之后能加快启动时间呢,因为lazy修饰的变量在访问时它才赋值
    1
    2
    3
    4
    5
    6
    7
    val gankApi: GankApi by lazy {
    val retrofit: Retrofit = Retrofit.Builder()
    .baseUrl(API_URL)
    .addConverterFactory(MoshiConverterFactory.create())
    .build()
    retrofit.create(GankApi::class.java)
    }

使用Data Classes(数据类)少写代码

  • 数据类是一个简单版的 Class,它自动添加了包括 equals(), hashCode(), copy(), 和 toString() 方法。将数据与业务逻辑分开。
    1
    data class User(val name: String, val age: Int)

Object Expressions(对象表达式)

  • Object Expressions 允许定义单例
  • 下面定义的ThreadUtil是对象不是class
  • 故可以直接调用ThreadUtil.onMainThread(runnable)
1
2
3
4
5
6
7
8
object ThreadUtil {

fun onMainThread(runnable: Runnable) {
val mainHandler = Handler(Looper.getMainLooper())
mainHandler.post(runnable)
}

}
  • 类似的可以直接匿名创建使用
    1
    view.setOnClickListener(object:View.OnClickListener);

Companion Object(伴生对象)

  • kotlin中是没有静态变量与方法的。
  • Companion Object 就类似于 Java 中的 static
    1
    2
    3
    4
    5
    class Util{
    companion object {
    const val URL = "https://github.com"
    }
    }
  • 使用URL
    1
    var url = Util.URL

Optional Parameters(可选参数)

  • 可选参数使得方法调用更加灵活
  • 可不必传递 null 或默认值。
    例如:
    1
    2
    3
    4
    5
    6
    7
    fun View.fadeOut(duration: Long = 500): ViewPropertyAnimator {
    return animate()
    .alpha(0.0f)
    .setDuration(duration)
    }
    icon.fadeOut() // 不传参数 默认为500
    icon.fadeOut(1000) // 传递参数 就替换默认值为1000

(noarg)data class 加无参构造 (allopen)去final

(noarg)data class 加无参构造

对于data class,有时候我们需要解决 default public constructor这样的问题,这个时候我们需要noarg,用法如下:

  • 首先你要做的就是定义一个注解:

    1
    annotation class PoKo
  • 接着 gradle 配置一下脚本的依赖:

    1
    2
    3
    4
    5
    6
    7
    8
    buildscript { 
    ...
    dependencies {
    ...
    classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
    ...
    }
    }
  • 加了运行时环境,那么我们就可以使用 noarg 插件了:

    1
    2
    3
    4
    5
    apply plugin: "kotlin-noarg" 
     
    noArg {
    annotation("net.println.kotlin.realm.PoKo")
    }
  • 给data class 加无参构造

    1
    @PoKo data class User(...) : RealmObject()

(allopen)去final

先解释下,java不是默认都是非final的么?不管是方法还是类
是的,但是kotlin这点比java做的好,它默认所有的类、变量、方法都是 final 的
如果想要继承呢?嗯,就是这里需要讲解的allopen,使用方式同noarg,示例如下:

  • 先定义一个注解:

    1
    annotation class PoKo // 可以跟 noarg 公用同一个注解,也可以自己另外单独定义一个,这个不要紧。
  • 接着 gradle 配置

    1
    2
    3
    4
    5
    6
    7
    8
    buildscript { 
    ...
    dependencies {
    ...
    classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
    ...
    }
    }
  • 应用插件

    1
    2
    3
    4
    5
    apply plugin: "kotlin-allopen" 
     
    allOpen {
    annotation("net.println.kotlin.realm.PoKo")
    }
  • 配置注解使用

    1
    2
    3
    4
    5
     @PoKo data class User(...) : RealmObject() 

    //可继承
    public class UserRealmProxy extends User
    implements RealmObjectProxy, UserRealmProxyInterface