class SQL : IDataPersistence {
override fun addData() {
Log.d("xys", "addData with SQL")
}
override fun delData() {
Log.d("xys", "delData with SQL")
}
override fun queryData() {
Log.d("xys", "queryData with SQL")
}
}
class SharedPreferences : IDataPersistence {
override fun addData() {
Log.d("xys", "addData with SharedPreferences")
}
override fun delData() {
Log.d("xys", "delData with SharedPreferences")
}
override fun queryData() {
Log.d("xys", "queryData with SharedPreferences")
}
}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.
第三步:调用约束接口,即业务方调用,但不用考虑具体的实现。类委托的语法格式是,<类>:<约束接口> by <实现类的实例>,即通过by关键字,将接口的实现,委托给一个具体的实例来作为自己的实现。
class MyDB(private val delegate: IDataPersistence) : IDataPersistence by delegate1.
使用方式与Java代码通过接口来实现基本一致,即在类初始化的时候,传入具体的实现类即可。
// val myDB = MyDB(SQL())
val myDB = MyDB(SharedPreferences())
myDB.addData()
myDB.delData()
myDB.queryData()1.2.3.4.5.
class MyDB(private val delegate: IDataPersistence) : IDataPersistence by delegate {
override fun addData() {}
override fun delData() {}
override fun queryData() {}
}1.2.3.4.5.6.7.
class Person {
var firstName: String = ""
set(value) {
field = value.toLowerCase()
}
var lastname: String = ""
set(value) {
field = value.toLowerCase()
}
}
调用:
val person = Person()
person.firstName = "XU"
person.lastname = "YISHENG"
println("${person.firstName} ${person.lastname}")1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.
class DemoFragment : Fragment() {
private var param1: Int by FragmentArgumentDelegate()
private var param2: String by FragmentArgumentDelegate()
companion object {
fun newInstance(param1: Int, param2: String): DemoFragment =
DemoFragment().apply {
this.param1 = param1
this.param2 = param2
}
}
}
@Suppress("UNCHECKED_CAST")
class FragmentArgumentDelegate<T : Any> : ReadWriteProperty<Fragment, T> {
override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
val key = property.name
return thisRef.arguments?.get(key) as T
}
override fun setValue(thisRef: Fragment, property: KProperty<*>, value: T) {
val arguments = thisRef.arguments
val key = property.name
arguments?.put(key, value)
}
}
fun <T> Bundle.put(key: String, value: T) {
when (value) {
is Boolean -> putBoolean(key, value)
is String -> putString(key, value)
is Int -> putInt(key, value)
is Short -> putShort(key, value)
is Long -> putLong(key, value)
is Byte -> putByte(key, value)
is ByteArray -> putByteArray(key, value)
is Char -> putChar(key, value)
is CharArray -> putCharArray(key, value)
is CharSequence -> putCharSequence(key, value)
is Float -> putFloat(key, value)
is Bundle -> putBundle(key, value)
is Parcelable -> putParcelable(key, value)
is Serializable -> putSerializable(key, value)
else -> throw IllegalStateException("Type of property $key is not supported")
}
}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.
var observableProp: String by Delegates.observable("init value 0") { property, oldValue, newValue ->
Log.d("xys", "change: $property: $oldValue -> $newValue ")
}
Log.d("xys", observableProp)
observableProp = "change value"1.2.3.4.5.6.
当属性值发生改变的时候,就会通知出来。
借助观察属性,可以很方便的实现时间差的判断,例如连续back退出的功能,代码如下所示。
private var backPressedTime by Delegates.observable(0L) { pre, old, new ->
if (new - old < 2000) {
finish()
} else {
Toast.makeText(this, "再按一次返回退出", Toast.LENGTH_SHORT).show()
}
}
override fun onBackPressed() {
backPressedTime = System.currentTimeMillis()
}1.2.3.4.5.6.7.8.9.10.11.
@Suppress("UNCHECKED_CAST")
class PreferenceDelegate<T>(private val context: Context, private val propName: String, private val defaultValue: T) : ReadWriteProperty<Any, T> {
private val sharedPreferences: SharedPreferences by lazy { context.getSharedPreferences("SP_NAME", Context.MODE_PRIVATE) }
override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
value?.let { putSPValue(propName, value) }
}
override fun getValue(thisRef: Any, property: KProperty<*>): T {
return getSPValue(propName, defaultValue) ?: defaultValue
}
private fun <T> getSPValue(name: String, defaultValue: T): T? = with(sharedPreferences) {
val result = when (defaultValue) {
is String -> getString(name, defaultValue)
is Int -> getInt(name, defaultValue)
is Long -> getLong(name, defaultValue)
is Float -> getFloat(name, defaultValue)
is Boolean -> getBoolean(name, defaultValue)
else -> null
}
result as T
}
private fun <T> putSPValue(name: String, value: T) = with(sharedPreferences.edit()) {
when (value) {
is Long -> putLong(name, value)
is String -> putString(name, value)
is Int -> putInt(name, value)
is Boolean -> putBoolean(name, value)
is Float -> putFloat(name, value)
else -> null
}
}?.apply()
}
使用:
var valueInSP: String by PreferenceDelegate(this, "test", "init")
Log.d("xys", valueInSP)
valueInSP = "new value"
Log.d("xys", valueInSP)
out:
D/xys: init
D/xys: new value1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.