kotlin-extension function

作者: 关内侯和他的五百勇士 | 来源:发表于2017-05-26 16:20 被阅读250次

    前言

    kotlin 的函数扩展可以给已知的任何 class 类添加函数,而不需要在写各种 utils 工具类,极大的解放了码农的天性
    三大高阶用法:
    type-safe builder 模式,扩展方法与扩展属性, lambda with receiver

    **一、 扩展函数 **
    使用 fun 来生成一个可以构建任何 Android View 的实例

    inline fun <reified TV : View> v(context: Context, init: TV.() -> Unit): TV{
      val constr = TV::class.java.getConstructor(Context::class.java)
      val view = constr.newInstance(context)
      view.init()
      return view
    }
    /**
    *<reified TV : View>   reify 意为具体化。
    *  而作为 kotlin 的一个方法泛型关键字,可以代表在方法体内访问泛型指定的 JVM 类对象。
    *  这段代码的意思是 v 方法要使用命名为 TV(即 Type of View) 的 reified 泛型,
    *  它指定类必须为 View 或其子类。
    *  必须以内联的方式声明该方法才有效。调用者必须给 TV 指定一个具体的类型
    *
    *init: TV.() -> Unit  v 方法的第二个参数是 lambda 风格的 init.
    *  init 是一种 lambda with receiver 类型的方法引用。是一个要求特定类型的对象的代码块,此处要求的对象在 lambda 代码中通过 this 关键字引用。这里 receiver 对象就是 reified 泛型 TV
    */
    // 接下来就可以在其他 Kotlin 代码中调用这个方法来创建并初始化任何类型的 View
    import android.view.ViewGroup.LayoutParams
    import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
    import android.widget.TextView
    
    var view = v<TextView>(context) {
        layoutParams = LayoutParams(WRAP_CONTENT,WRAP_CONTENT)
        text = "hello"
     }
    

    扩展 函数支持 dp-px转换

    fun View.dp_f(dp: Float): Float {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,context.resources.displayMetrics)
    }
    
    fun View.dp_i(dp: Float): Int {
      return dp_f(dp).toInt()
    } 
    

    二、 扩展属性
    对于当前已经存在的类(自定义或者Java/Android SDK 类)都可以进行动态扩展属性:
    1、 为自定义类扩展属性

    //自定义类
    data class User(val name: String, val age: Int){}
    // 为 User 类添加 gender 属性
    // 声明通过 ProProxy 代理类来为 User 添加属性
    var User.email: String by ProProxy()
    // ProProxy class
    class ProProxy {
        operator fun getValue(thisRef: Any?, pro: kotlin.reflect.KProperty<*>): String {
           return thisRef?.variablesMap?.get(pro.toString()) as String
      }
        operator fun setValue(thisRef: Any?, pro: kotlin.reflect.KProperty<*>, value: Any) {
           thisRef?.variablesMap?.set(pro.toString(),value)  
      }
    }
    // 定义 ProProxy 的 variablesMap,通过 mutableMap来保存 当前对象 thisRef 的所有属性
    private val Any.variablesMap by lazy {
      val mutableMap: MutableMap<String, Any> = mutableMapOf()
      mutableMap
    }
     // 现在就可以使用 User.gender 属性了
    fun main(args: Array<String>) {
      User().gender = "female"
    }             
    

    2、为系统/SDK类扩展属性

    var View.leftPadding: Int
          // 指定 setter 方法,类型为 Int
           set(value) {
              // 通过 View.setPadding 方法设置左边距,对于其他的参数使用 Kotlin 模拟变量
              setPadding(value,paddingTop,paddingRight,paddingBottom)
            }
            get() {
              return paddingLeft
            }
    

    一个可变的扩展属性需要同时提供 getter 和 setter 方法

    实战 Kotlin@Android(一):项目配置和语言转换
    实战 Kotlin@Android(二):界面构建与扩展方法
    实战 Kotlin@Android(三):扩展变量与其它技巧

    相关文章

      网友评论

        本文标题:kotlin-extension function

        本文链接:https://www.haomeiwen.com/subject/lpntfxtx.html