懒加载
lateinit
懒加载,则用于只能生命周期流程中进行获取或者初始化的变量,比如 Android 的 onCreate(),修饰var
lazy函数
1
|
public fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer) |
使用:
1 2 3 4 5 6 7 8 9 10 11 |
//得到lazy对象
val init = lazy(LazyThreadSafetyMode.SYNCHRONIZED) { TextView(this).apply {
textSize = sp(10f).toFloat()
textColor = Color.BLUE}
}
//或者 不设置参数
val init = lazy { TextView(this).apply {
textSize = sp(10f).toFloat()
textColor = Color.BLUE}
} |
懒加载,与by经常一起使用,修饰val
by 委托模式
Kotlin中,委托的实现依靠于关键字by表示将抽象主题的实例(by后边的实例)保存在代理类实例的内部
定义语法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
val/var <property name>: <Type> by <expression>
比如: val a:Int by lazy {2}
比如:
interface ISports {
fun doSports()
}
class SwimForSports: ISports{
override fun doSports() {
println("do swim")
}
}
class SportsManager(sport: ISports): ISports by sport
fun main(args: Array<String>) {
val swimSports: SwimForSports = SwimForSports()
SportsManager(swimSports).doSports()// Log:do swim
} |
- var/val:属性类型(可变/只读)
- name:属性名称
- Type:属性的数据类型
- expression:代理类
可观察属性(Observable)与Vetoable
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var name: String by Delegates.observable("wang", {
kProperty, oldName, newName ->
println("kProperty:${kProperty.name} | oldName:$oldName | newName:$newName")
})
fun main(args: Array<String>) {
println("name: $name") // Log:nam:wang
name = "zhang" // Log:kProperty:name | oldName:wang | newName:zhang
name = "li" // Log:kProperty:name | oldName:zhang | newName:li
} |
区别是Vetoable会有返回值,如果返回值是true,才允许赋值
Not Null
1 2 3 4 5 6 7 8 9 10 |
class App : Application() {
companion object {
var instance: App by Delegates.notNull()
}
override fun onCreate() {
super.onCreate()
instance = this
}
} |
将多个属性保存在一个map内
1 2 3 4 |
class User(val map: Map<String, Any?>) {
val name: String by map
val age: Int by map
} |
自定义委托模式 可参考Observable或者与Vetoable
ReadOnlyProperty接口主要用于实现只读属性的属性委托。
ReadWriteProperty接口主要用于实现可变属性的属性委托。
创建一个委托类SingleValueVar,继承自ReadWriteProperty
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class SingleValueVar<T> : ReadWriteProperty<Any?, T> {
private var value: T? = null
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
if (null != value && null == this.value) {
this.value = value // 只允许了初次修改
}
}
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return value!!
}
} |
为属性设置委托
1 2 3 4 5 6 7 |
class Student {
var no: Int by SingleValueVar<Int>()
var name: String = "wang"
override fun toString(): String {
return "no: $no | name: $name"
}
} |
##### 测试实例
fun main(args: Array
1 2 3 4 5 6 7 8 9 |
stu.no = 20
stu.name = "wang"
println(stu.toString()) // 打印:no: 20 | name: wang
stu.no = 30
stu.name = "li"
println(stu.toString()) // 打印:no: 20 | name: li
} |
高阶函数
let函数
1 2 3 4 5 6 |
public inline fun <T, R> T.let(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
} |
适用于处理不为null的操作场景
### also函数
1 2 3 4 5 6 7 |
public inline fun <T> T.also(block: (T) -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block(this)
return this
} |
适用于let函数的任何场景,一般可用于多个扩展函数链式调用
with函数
不是拓展函数
1 2 3 4 5 6 |
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return receiver.block()
} |
适用于调用同一个类的多个方法时,可以省去类名重复,直接调用类的方法即可,经常用于Android中RecyclerView中onBinderViewHolder中,数据model的属性映射到UI上
### run函数
1 2 3 4 5 6 |
public inline fun <R> run(block: () -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
} |
适用于let,with函数任何场景。
apply函数
1 2 3 4 5 6 7 |
public inline fun <T> T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
} |
- 适用于run函数的任何场景,一般用于初始化一个对象实例的时候,操作对象属性,并最终返回这个对象。
- 动态inflate出一个XML的View的时候需要给View绑定数据也会用到.
- 一般可用于多个扩展函数链式调用
- 数据model多层级包裹判空处理的问题