懒加载
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多层级包裹判空处理的问题