Delegates实现双击back退出
简介
说Delegates之前,首先必须了解下kotlin的委托机制,这个委托机制还是很不错的,可以将一个对象的构造和设置值,都给委托给其它
委托机制
关键词by,是不是很眼熟,这不是我们经常用过的by lazy{} ,没错懒加载就是用委托实现的
自定义委托
考大家一个问题val和var有啥区别吗?val是不可变的变量,必须要在初始化化的时候赋值。var是可变的变量。有没有考虑过为啥呢?
// 其实每个变量都有一个隐藏的方法,如果是val变量修饰,只有get方法 val name: String = "" get() {
return field } // var 有get方法和set方法,当你给name2进行赋值的时候,set方法就会调用 var name2: String = "" get() {
return field } set(value) {
}
来尝试来一个定义一个委托:
这里描述下,我现在是
val定义变量,只需要ReadOnlyProperty(只需要要委托getValue方法),我定义了一个value变量记录值(初始化内容123),当使用这个变量的读取这个值的时候,就会调用我的委托方法
val name: String by object : ReadOnlyProperty<Any?, String> {
var value: String = "123" override fun getValue(thisRef: Any?, property: KProperty<*>): String {
println("取这个[${property.name}]属性赋值:$value") // 返回这个记录值 return value } } // 同理var的委托定义,如果我这样写,当使用这个变量的读取这个值的时候,就会调用我的委托方法。当我设置值的时候就会调用我的set方法,会传入一个value方法。 var name2: String by object : ReadWriteProperty<Any?, String> {
var value: String = "123" override fun getValue(thisRef: Any?, property: KProperty<*>): String {
println("取这个[${property.name}]属性赋值:$value") // 返回这个记录值 return value } override fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("为这个[${property.name}]属性赋值:$value") // 记录下当前这个值 this.value = "我是从新构造:$value" } }
这里有必要说下 thisRef 是个什么鬼?就是这个变量对应在那个对象中
曲线救国委托实现多继承
interface A {
fun call() } class B() : A {
override fun call() {
println("我调用call了") } } open class D() {
fun core() {
println("我调用core了") } } class C() : D(), A by B(){
fun test(){
// todo 我可以直接掉call 变向多继承(这个在协程的 协程上下文与调度器(5)--协程作用域(重点) 有用到) call() } }
Delegates
Delegates.notNull
// 使用很简单 val name:String by Delegates.notNull<String>() // 源码分析 // 第一句没啥的看下,NotNullVar public fun <T : Any> notNull(): ReadWriteProperty<Any?, T> = NotNullVar() // 是不是看出来了,在取值的时候,如果是null就会抛异常 private class NotNullVar<T : Any>() : ReadWriteProperty<Any?, T> {
private var value: T? = null public override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return value ?: throw IllegalStateException("Property ${property.name} should be initialized before get.") } public override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
this.value = value } }
Delegates.observable
大家记住这个,用它可以完成双击back退出
val name: String by Delegates.observable("初始化值") {
pre, old, new -> log("以前的值$old 新设置的值$new") }
// 这里没啥好说的,主要看下 ObservableProperty对象 public inline fun <T> observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit): ReadWriteProperty<Any?, T> = object : ObservableProperty<T>(initialValue) {
// 注意这里重写了afterChange方法 // 这里是调用onChange方法,就是我们传入的lambda表达式 override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue) }
public abstract class ObservableProperty<T>(initialValue: T) : ReadWriteProperty<Any?, T> {
private var value = initialValue protected open fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = true protected open fun afterChange(property: KProperty<*>, oldValue: T, newValue: T): Unit {
} public override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return value } // 主要是这里, public override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
// 记录上一次的值 val oldValue = this.value // beforeChange默认返回true,先不管 if (!beforeChange(property, oldValue, value)) {
return } // 为this.value设置新的值,为getValue做准备 this.value = value // 调用afterChange方法,被重写了,所以会调用到onChange,是不是很简单 afterChange(property, oldValue, value) } }
Delegates.vetoable
这个能在设置值的时候,加逻辑判断,如果不满足便不更新值
val name: String by Delegates.vetoable("初始化值") {
pre, old, new -> // 如果设置的新值是a开头的就设置新值,返回ture就修改,false就不修改 new.startsWith("a") }
public inline fun <T> vetoable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Boolean): ReadWriteProperty<Any?, T> = object : ObservableProperty<T>(initialValue) {
// 注意这里重写的是beforeChange方法 override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = onChange(property, oldValue, newValue) }
接下来就和以前差不多了
public abstract class ObservableProperty<T>(initialValue: T) : ReadWriteProperty<Any?, T> {
private var value = initialValue protected open fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = true protected open fun afterChange(property: KProperty<*>, oldValue: T, newValue: T): Unit {
} public override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return value } // 主要是这里, public override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
// 记录上一次的值 val oldValue = this.value // 主要看这里 // beforeChange写了,如果我们的lamabda表达式返回的ture就不会return,就会调用后面的赋值方法 if (!beforeChange(property, oldValue, value)) {
return } // 为this.value设置新的值,为getValue做准备 this.value = value // 调用afterChange方法,被重写了,所以会调用到onChange,是不是很简单 afterChange(property, oldValue, value) } }
实践完成双击back退出
其实很简单,就是使用observable的特性
private var backPressedTime by Delegates.observable(0L) {
pre, old, new -> // 2次的时间间隔小于2秒就退出了 if (new - old < 2000) {
finish() } else {
drawerLayout?.snack("再按返回鍵退出") } } // 从新写back方法 override fun onBackPressed() {
// 直接赋值就可以啦,是不是很简单呀 backPressedTime = System.currentTimeMillis() }
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/199338.html原文链接:https://javaforall.net
