KT的语法太灵活,再写一篇
单例
//Java实现
public class SingletonDemo {
private static SingletonDemo instance=new SingletonDemo();
private SingletonDemo(){
}
public static SingletonDemo getInstance(){
return instance;
}
}
//Kotlin实现
object SingletonDemo //生成字节码类似上面
SingletonDemo.INSTANCE
class区别
原因是在kotlin中的Class与Java不同,kotlin中有一个自己的Class叫做KClass,person::class 和Person::class都是获取kotlin的KClass,所以println(person::class == Person::class) 为true。
我们可以从kotlin的KClass获取到java的Class,person::class.java就是如此,先获取到kotlin的KClass然后再获取javaClass。
object/class->kClass->Class
同样也可以通过java的Class获取kotlin的KClass,person.javaClass.kotlin就是先获取javaClass然后再获取kotlin的KClass
object/class->Class->KClass
let、with、run、apply、also函数的使用
let 函数的是一个不错的选择;let函数另一个作用就是可以避免写一些判断null的操作。
返回值为函数块的最后一行或指定return表达式
with函数它是将某对象作为函数的参数,在函数块内可以通过 this 指代该对象。返回值为函数块的最后一行或指定return表达式于with函数最后一个参数是一个函数,可以把函数提到圆括号的外部
run函数适用于let,with函数任何场景。因为run函数是let,with两个函数结合体
apply,run函数是以闭包形式返回最后一行代码的值,而apply函数的返回的是传入对象的本身, 多层级判空问题
also函数的结构实际上和let很像唯一的区别就是返回值的不一样,let是以闭包的形式返回,返回函数体内最后一行的值,如果最后一行为空就返回一个Unit类型的默认值。而also函数返回的则是传入对象的本身
//另一种用途 判断object为null的操作
object?.let{//表示object不为null的条件下,才会去执行let函数体
it.todo()
}
with(object){
//todo
}
const val 和val
从字节码我们可以看到const val 和val修饰对象的主要区别是:
const val 可见性为public final static,可以直接访问。
val 可见性为private final static,并且val 会生成方法getNormalObject(),通过方法调用访问。
当定义常量时,出于效率考虑,我们应该使用const val方式,避免频繁函数调用。
typealias Username = String
内联类
然而,内联类的成员也有一些限制:
内联类不能含有 init 代码块
内联类不能含有 inner 类
内联类不能含有幕后字段
常用注解
@JvmStatic
用于让java中调用kotlin的单例中的方法不用写INSTANCE
@JvmField val BIG_INTEGER = BigInteger.ONE //指示 kotlin 编译器不要为此属性生成 getters/setters,
@JvmStatic fun method() {
println("call method")
}
@JvmOverloads 自动重载多个方法
@Throws 异常注解
可见性
在Kotlin中有四种可见性修饰符: private, protected, internal, public
如果没有指定,则默认是public
类/对象/接口/构造函数/方法/属性和setter都有可见性修饰符(getter与属性可见性相同
定义
描述状态时,用属性;描述行为时,用函数
指定如果它是函数,则需要从此元素生成额外的静态方法。如果此元素是属性,则应生成额外的静态 getter / setter 方法
lazy 文档 创建的新实例懒惰使用指定的初始化函数初始化和默认的线程安全模式LazyThreadSafetyMode.SYNCHRONIZED
by lazy 与 lateinit 不同的是 在使用lateinit 定义的变量前 一定会给他一个实例 保证他不会是空对象 而 by lazy 则是在第一次使用时 初始化对象
Kotlin中的委托 他分为两种 一种是属性委托 一种是类委托
lazy 属性的求值是同步锁的(synchronized):该值只在一个线程中计算,并且所有线程会看到相同的值。如果初始化委托的同步锁不是必需的,这样多个线程可以同时执行,那么将 LazyThreadSafetyMode.PUBLICATION 作为参数传递给 lazy() 函数。 而如果你确定初始化将总是发生在与属性使用位于相同的线程, 那么可以使用 LazyThreadSafetyMode.NONE 模式:它不会有任何线程安全的保证以及相关的开
this@xxx 内部类中标志外部对象
协程
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
coroutine.setOnClickListener { click() }
}
private fun click() = runBlocking {
GlobalScope.launch(Dispatchers.Main) {
coroutine.text = GlobalScope.async(Dispatchers.IO) {
// 比如进行了网络请求
// 放回了请求后的结构
return@async "main"
}.await()
}
}
}
Android中只有2种类型的线程:MainThread(主线程) 和 WorkerThread。
反引号
反引号(键盘左上角和波浪线在一起的符号) ``
在Kotlin中可以用反引号解决关键字冲突的问题,可以强行将一个不合法的字符变为合法。
我们知道在Kotlin中有一个关键字internal,被这个关键字修饰的函数可以被同一个module中任何方法调用。但是在Java又没有这个修饰符,而且Java和Kotlin是100%兼容的,那么这个时候Java在调用这个函数的时候会把他当成public来处理,这显然不是我们想要的。那么该如何让一些函数不能被Java调用呢?这个时候就可以使用反引号来引用一些Java中没有特殊方法来处理这个问题。
fun `123`(){
println("this is message")
}
kotlin不同模块相互调用
1,library的 depenencies 不能用implementation因为implementation无法继承,所以要使用api这个,是可以继承的。
2,如果相互调用报错:unresolved reference 。那是因为library需要 apply plugin: 'kotlin-andoid ’
gradle配置
在lib工程中加入consumerProguardFiles ‘proguard-rules.pro’,这个配置会在lib工程被打包的时候让lib工程中的proguard-rules.pro生效,此时lib工程就会按照它自己的proguard-rules.pro文件配置被正确混淆
resourcePrefix “${project.name}_” //给 Module 内的资源名增加前缀, 避免资源名冲突
库
JavaPoet - 优雅地生成代码
插件
kapt是kotlin的注解处理器,用法很简单
在 Kotlin 中则需要添加 kotlin-kapt 插件激活 kapt,并使用 kapt 替换 annotationProcessor:
配置 在app build.gradle 中 激活
Kotlin Android Extensions遭废弃,官方推荐使用ViewBinding
com.android.library 编译库工具
kotlin-android kt安卓支持