1 常见问题
1.1 please select android sdk
问题描述:提示选择 sdk 版本,但是已经配置 sdk。as 清理缓存、clean 都不行,external libraries 中没有 Android API 只有一个 Kotlin SDK
解决方案:在主 module 下 app.iml 中替换如下:
<orderEntry type="jdk" jdkName="Kotlin SDK" jdkType="KotlinSDK" />
替换为:
<orderEntry type="jdk" jdkName="Android API 27 Platform" jdkType="Android SDK" />
参考: please select android sdk(出现小红叉)
1.2 如何查看 kotlin 编译后的 java 代码
How to show Java equivalent for Kotlin code
2 知识点
2.1 lateinit 和 by lazy
2.2 operator 操作符重载
2.3 inline 内联函数的使用
应用场景如下:
内联函数与普通的函数有点不同。一个内联函数会在编译的时候被替换
掉,而不是真正的方法调用。这在一些情况下可以减少内存分配和运行时
开销。举个例子,如果我们有一个函数,只接收一个函数作为它的参数。
如果是一个普通的函数,内部会创建一个含有那个函数的对象。另一方
面,内联函数会把我们调用这个函数的地方替换掉,所以它不需要为此生
成一个内部的对象。
如:我们可以创建代码块只提供 Lollipop 或者更高版本来执行:
inline fun supportsLollipop(code: () -> Unit){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
code()
}
}
它只是检查版本,然后如果满足条件则去执行。现在我们可以这么做:
supportsLollipop{
window.setStatusBarColor(Color.BLACK)
}
举个例子,Anko也是基于这个思想来实现 Android Layout 的 DSL 化。你也可
以查看 Kotlin reference 中 使用DSL来编写HTML 的一个例子。
2.4 委托属性
我们可能需要一个属性具有一些相同的行为,使用 lazy 或者 observable 可以被很有趣地实现重用。而不是一次又一次地去声明那些相同的代码,Kotlin 提供了一个委托属性到一个类的方法。这就是我们知道的委托属性 。当我们使用属性 get 或者 set的时候,属性委托的 getValue 和 setValue 就会被调用。 属性委托的结构如下:
class Delegate<T> : ReadWriteProperty<Any?, T> {
fun getValue(thisRef: Any?, property: KProperty<*>): T {
return ...
}
fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
...
}
}
这个T是委托属性的类型。 getValue 函数接收一个类的引用和一个属性的元数据。
setValue 函数又接收了一个被设置的值。如果这个属性是不可修改(val),就会只有一个 getValue 函数。
下面展示属性委托是怎么设置的:
class Example {
var p: String by Delegate()
}
它使用了 by 这个关键字来指定一个委托对象。
Kotlin 标准委托 lazy
Lazy:
它包含一个lambda,当第一次执行 getValue 的时候这个lambda会被调用,所以
这个属性可以被延迟初始化。之后的调用都只会返回同一个值。这是非常有趣的特
性, 当我们在它们第一次真正调用之前不是必须需要它们的时候。我们可以节省内
存,在这些属性真正需要前不进行初始化。
class App : Application() {
val database: SQLiteOpenHelper by lazy {
MyDatabaseHelper(applicationContext)
}
override fun onCreate() {
super.onCreate()
val db = database.writableDatabase
}
}
在这个例子中,database并没有被真正初始化,直到第一次调用 onCreate 时。
在那之后,我们才确保applicationContext存在,并且已经准备好可以被使用
了。lazy 操作符是线程安全的。
如果你不担心多线程问题或者想提高更多的性能,你也可以使
用 lazy(LazyThreadSafeMode.NONE){ ... }。
其他标准委托如:observable、vetoable、notNull 等参见 kotlin-for-android-developers