前言
Kotlin
是一种在Java
虚拟机上运行的静态类型编程语言,被称之为Android
世界的Swift
,在Google
I/O2017中,Google
宣布Kotlin
成为Android
官方开发语言
将属性委托给另一个属性
一个属性可以把它的set/get
方法委托给另一个属性,属性View的get/set
委托给了ViewDelegate
去做
class TestActivity:DaggerAppCompatActivity(){
var view:View by ViewDelegate()
}
class ViewDelegate{
var view:View? = null
operator fun getValue(thisRef:Activity?,kProperty: KProperty<*>):View{
return View(thisRef).also { view = it }
}
operator fun setValue(thisRef: Activity?, property: KProperty<*>, value: View) {
this.view = value
}
}
如果是个只读属性,则只需要提供一个getValue
函数,用于委托属性的获取
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, 这里委托了 ${property.name} 属性"
}
-
thisRef
表示属性的作用域 -
property
是KProperty
的子类型 - 返回属性的类型
如果是一个可变属性,则需要添加一个setValue
函数
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$thisRef 的 ${property.name} 属性赋值为 $value")
}
-
thisRef
表示属性的作用域 -
property
是KProperty
的子类型 -
value
表示所设置的内容
委托属性的编译
class Example {
var value: String by Delegate()
}
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, 这里委托了 ${property.name} 属性"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$thisRef 的 ${property.name} 属性赋值为 $value")
}
}
上述的代码会生成类似这样的代码
class Example{
public String p$delegate = new Delegate()
public String value;
public getValue(){
return p$delegate.getValue()
}
public setValue(String v){
return p$delegate.setValue(this,::value,v)
}
}
委托属性的应用
我们在Android
中会经常使用DataBinding
将UI
绑定到代码中去,通常它的使用方式是这样
DataBindingUtil.inflate(layoutInflater, layoutRes, null, false)
如果我们有多个Activity
都在对其进行使用
class LoginActivity : DaggerAppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding:LoginDataBinding = DataBindingUtil.inflate(layoutInflater, R.layout.login, null, false)
}
}
class RegisterActivity : DaggerAppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding:RegisterDataBinding = DataBindingUtil.inflate(layoutInflater, R.layout.register, null, false)
}
}
上述代码中的
- 不同部分:只有一个变量部分就是
layout resource ID
- 公共部分:都是使用在
Actiivty
中,都返回了一个ViewDataBinding
对象
我们可以将他们抽离出来,将生成Binding
的过程委托给委托类去做
- 委托类需要提供能够生成
ViewDataBinding
的能力,所以它的返回类型应该是DataBinding
的子类型 - 由于我们是在多个
Activity
中对其进行使用,所以他的作用域应该是Activity
的子类型
class ViewDelegate<in R : DaggerAppCompatActivity, out T : ViewDataBinding>() {
operator fun getValue(thisRef: R, property: KProperty<*>): T {
return DataBindingUtil.inflate(thisRef.layoutInflater, 0, null, false)
}
}
- 布局
Resource ID
是一个需要外部传入的部分,可以通过构造函数传入
class ViewDelegate<in R : DaggerAppCompatActivity, out T : ViewDataBinding>(@LayoutRes private var layoutRes: Int) {
operator fun getValue(thisRef: R, property: KProperty<*>): T {
return DataBindingUtil.inflate(thisRef.layoutInflater, layoutRes, null, false)
}
}
4.然后就可以使用委托的方式初始化ViewDataBinding
class LoginActivity : DaggerAppCompatActivity() {
val binding: AtctivityLoginBinding by ViewDelegate(R.layout.atctivity_login)
}
欢迎关注Mike的简书
Android知识整理