委托属性是kotlin一个非常好用的特性,它可以让我们通过类来封装控制属性的set和get方法,通过这种方式来复用代码,能让代码更加简洁,下面看看它在Android开发中的应用。
案例:如果要实现在给String类型的属性赋值时,去掉字符串两边的空格,最常见的实现方式是这样的。
这样操作没什么问题,但是如果有很多个String属性,都需要这个功能,那么代码就会比较重复,而且看上去会很乱。如果是使用委托属性,我们需要先定义一个类,实现ReadWriteProperty<T, V>接口,用来处理String属性的set和get方法,T表示限定声明属性所属类的类型,V表示限定属性自身的类型,这里不限定是某种类的String属性,所以实现接口ReadWriteProperty<Any?, String>,如果限定XX类的String属性,改为实现ReadWriteProperty<XX, String>即可。
在需要实现该功能的属性上使用by TrimDelegate()
即可,如下
如果有很多属性都需要该功能,使用委托属性可以非常明显的简化代码,下面是一个完整示例,可在线运行查看效果。
1import kotlin.properties.ReadWriteProperty
2import kotlin.reflect.KProperty
3
4class TrimDelegate : ReadWriteProperty<Any?, String> {
5
6 private var trimmedValue: String = ""
7
8 override fun getValue(
9 thisRef: Any?,
10 property: KProperty<*>
11 ): String {
12 return trimmedValue
13 }
14
15 override fun setValue(
16 thisRef: Any?,
17 property: KProperty<*>, value: String
18 ) {
19 trimmedValue = value.trim()
20 }
21}
22
23class Example {
24 var param1 by TrimDelegate()
25 var param2: String = ""
26}
27
28fun main() {
29 val example = Example()
30 example.param1 = " 知行课堂 "
31 println("##" + example.param1 + "##")
32 example.param2 = " 知行课堂 "
33 println("##" + example.param2 + "##")
34}
35
在Android开发中,在Fragment中一般使用arguments来进行传参,在创建Frament时,把参数设置在arguments中。
然后在Fragment的onCreate中通过arguments来读取参数,然后保存至成员属性中。
下面看看如何使用委托属性来简化,为了统一处理Bundle各种类型的参数,先给Bundle添加一个扩展方法。
接下来是实现委托类,因为是针对Fragment类的所有类型属性,所以实现接口ReadWriteProperty<Fragment, T?>,在getValue方法中,我们根据属性的名字从Fragment的arguments中读取数据,在setValue时把数据保存到Fragment的arguments中。
在声明属性和给属性赋值时这样使用,就会从arguments中获取和保存至arguments中。
为了更加简化声明属性的代码,我们可以定义一个方法argument()
来替换FragmentArgumentDelegate。
同样的在使用SharedPreferences时,我们也会从SharedPreferences中获取值,在更新值的时候同步到SharedPreferences中,代码会是这样的。
如果属性很多,这样的代码就会很重复,我们一样可以通过委托属性来优化这段代码,之前我们都是定义一个类来代理属性,这里之前有些不一样,这个地方会依赖具体的preferences
,我们有两种方式可以处理,一种是将preferences作为参数传入到委托类中,第二种就是使用扩展方法。
在声明属性的地方改成这样即可。
这样是不是比之前更加简洁了?下面是上面示例的完整代码。
文件 | 大小 | 修改时间 |
---|---|---|
app | 2022年03月18日 | |
build.gradle | 358 B | 2022年03月18日 |
gradle/wrapper | 2022年03月18日 | |
gradle.properties | 1 kB | 2022年03月18日 |
gradlew | 6 kB | 2022年03月18日 |
gradlew.bat | 3 kB | 2022年03月18日 |
local.properties | 437 B | 2022年03月18日 |
settings.gradle | 333 B | 2022年03月18日 |