Kotlin中的委托属性
Kotlin 是 Jetbrain 推出的一门运行在 JVM 上的语言,它结合了面向对象以及函数式语言的特性,超甜的语法糖以及来自知名 IDE 大厂 Jetbrain 的出身让它初一面世就广受瞩目,特别是在 Android 开发社区中。它相比起 Java 拥有了许许多多的优秀特性,并且几乎每一个新特性都对应解决了 Java 开发时的痛苦之处,本篇文章主要讲解 Kotlin 中的委托属性这一特性。
委托属性(Delegated Properties)
我们先看看官网的定义:
有一些种类的属性,虽然我们可以在每次需要的时候手动实现它们,但是如果能够把他们之实现一次 并放入一个库同时又能够一直使用它们那会更好。例如:
- 延迟属性(lazy properties): 数值只在第一次被访问的时候计算。
- 可控性(observable properties): 监听器得到关于这个特性变化的通知,
- 把所有特性储存在一个映射结构中,而不是分开每一条。
为了支持这些(或者其他)例子,Kotlin 采用 委托属性。
简言之就是简化手动实现的属性,将其抽象出一个库。
如何使用
定义一个委托
Kotlin 中有两种属性:用var
修饰的可变属性和由val
修饰的只读属性。由val
修饰的只读属性使用的委托需要实现ReadOnlyProperty
,而var
修饰的可变属性则需要实现ReadWriteProperty
在调用被委托的属性的getter
和setter
时,对应操作会被委托给getValue()
以及setValue()
。
如实现一个最简单的委托Delegate
:
1 | class Delegate { |
使用定义好的委托属性
语法为val/var <property name>: <Type> by <expression>
1 | class Example { |
by
后面的是委托表达式,我们调用这个对象并使用属性:
1 | val e = Example() |
打印结果为:
1 | Example@33a17727, thank you for delegating 'p' to me! |
如上可知,thisRef
对应的是拥有该被委托属性的对象实例,property
则是属性,value
是调用setter
时的传入值。
实例讲解
lazy 懒加载
Kotlin 标准库自带的懒加载委托,在属性第一次被使用时才进行初始化。
函数lazy()
接受一个 lambda 然后返回一个可以作为委托Lazy<T>
实例来实现延迟属性: 第一个调用getter
执行变量传递到lazy()
并记录结果, 后来的getter
调用只会返回记录的结果。
1 | val lazyValue: String by lazy { |
其打印结果:
1 | computed! # 第一次使用时先初始化 |
懒加载委托在实际编码中应用十分广泛,比如 Android 中我们可以把很多在OnCreate
中需要进行的初始化操作使用懒加载委托来实现。
使用委托操作 SharedPreferences
本例出自《Kotlin for Android Developer》,使用了when
表达式和委托属性巧妙地使得SharedPrefences
的读写变得十分简便
1 | class Preference<T>(val context: Context, val name: String, val default: T) : ReadWriteProperty<Any?, T> { |
在代码中我们可以如下使用
1 | class WhateverActivity : Activity() { |
从此操作SharedPreferences
变得如此简单 ~
简单实现一个 KotterKnife
KotterKnife 是一个 Android 控件依赖注入框架,使用它可以很方便地初始化 Activity、Fragment、View 等的控件。
KotterKnife 的实现原理就是使用了委托属性,下面我就使用委托属性简单实现一个 View 注入功能
实现
我们平时是这样初始化 View 的
1 | override fun onCreate(savedInstanceState: Bundle?) { |
考虑到通常我们在onCreate
方法中将其初始化,我们可以用 lazy 委托,在第一次使用该控件的时候才将其初始化,这样可以减少不必要的内存消耗。
1 | val mTextView by lazy { |
对其抽取简化
1 |
|
之后我们就可以在 Activity 中这样注入 View 了
1 | val mTextView by bindView<TextView>(R.id.text_view) |
如上实现了类似 KotterKnife 的控件注入功能,当然 KotterKnife 中还有更加强大的可选绑定以及数组绑定,本文中我们就不细说了,有兴趣的读者可以阅读 KotterKnife源码。
小结
本文分析了 Kotlin 中的委托属性,并对其实际应用做了示例分析。委托属性是 Kotlin 语言的一个特性,灵活使用可以解决实际编码中的许多问题,减少大量重复代码,而由于其与属性的getter
、setter
直接绑定所以使用起来也十分灵活方便。
总而言之:这真是极好的。