Koltin中的代理属性 - 自定义委托

前言

Kotlin是一种在Java虚拟机上运行的静态类型编程语言,被称之为Android世界的Swift,在GoogleI/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表示属性的作用域
  • propertyKProperty的子类型
  • 返回属性的类型

如果是一个可变属性,则需要添加一个setValue函数

operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
    println("$thisRef 的 ${property.name} 属性赋值为 $value")
}
  • thisRef表示属性的作用域
  • propertyKProperty的子类型
  • 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中会经常使用DataBindingUI绑定到代码中去,通常它的使用方式是这样

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的过程委托给委托类去做

  1. 委托类需要提供能够生成ViewDataBinding的能力,所以它的返回类型应该是DataBinding的子类型
  2. 由于我们是在多个Activity中对其进行使用,所以他的作用域应该是Activity的子类型
class ViewDelegate() {
    operator fun getValue(thisRef: R, property: KProperty<*>): T {
        return DataBindingUtil.inflate(thisRef.layoutInflater, 0, null, false)
    }
}
  1. 布局Resource ID是一个需要外部传入的部分,可以通过构造函数传入
class ViewDelegate(@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知识整理

你可能感兴趣的:(Koltin中的代理属性 - 自定义委托)