美文网首页Kotlin
在Android中使用Kotlin扩展

在Android中使用Kotlin扩展

作者: 云飞扬1 | 来源:发表于2019-08-28 17:57 被阅读0次

    在 Java 中如果我们要为类添加新功能,就必须使用继承或者像装饰者这样的设计模式,但是在 Kotlin 中这些可以通过叫做扩展的方式来完成。平时我们开发 Android 的过程中,会逐渐总结出各种各样的工具类,如果使用 Kotlin 则可以通过扩展的方式,来简化或者替代这些工具类。

    Kotlin 扩展包括扩展属性、扩展函数 2 种方式,具体语法这里不多说了,主要讲讲通过扩展,在 Android 开发中可以为我们带来哪些便利。

    1. 替代View.setOnClickListener方法

    在 Java 中为一个 View 设置点击事件,我们必须这样写:

    view.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
        }
    });
    

    如果一个页面中要为很多 View 设置点击事件,写起来巨繁琐,在 Kotlin 中我们可以为 View 扩展一个函数来轻松实现点击事件:

    fun <T : View> T.click(block: (T) -> Unit) {
        setOnClickListener {
            block(this)
        }
    }
    

    这个时候,我们为 View 设置点击事件可以这样写:

    view.click {
       //处理点击事件逻辑
    }
    

    在写法上是不是简单多了,除此之外还可通过扩展属性来实现更高级功能。举个栗子,我们不希望某个按钮被频繁点击,在 Java 中的做法是设置一个变量记录点击时间,如果在某个时间间隔内再次触发点击,则不响应此事件。使用 Kotlin 我们可以这样实现该功能:

    先为 View 扩展 2 个属性:

    //私有扩展属性,允许2次点击的间隔时间
    private var <T : View> T.delayTime: Long
        get() = getTag(0x7FFF0001) as? Long ?: 0
        set(value) {
            setTag(0x7FFF0001, value)
        }
    
    //私有扩展属性,记录点击时的时间戳
    private var <T : View> T.lastClickTime: Long
        get() = getTag(0x7FFF0002) as? Long ?: 0
        set(value) {
            setTag(0x7FFF0002, value)
        }   
    

    再为 View 扩展一个方法:

    //私有扩展方法,判断能否触发点击事件
    private fun <T : View> T.canClick(): Boolean {
        var flag = false
        var now = System.currentTimeMillis()
        if (now - this.lastClickTime >= this.delayTime) {
            flag = true
            this.lastClickTime = now
        }
        return flag
    }
    
    //扩展点击事件,默认 500ms 内不能触发 2 次点击
    fun <T : View> T.clickWithDuration(time: Long = 500, block: (T) -> Unit) {
        delayTime = time
        setOnClickListener {
            if (canClick()) {
                block(this)
            }
        }
    }
    

    在 Kotlin 中使用,我们只需这样调用:

    //只有间隔1秒之后,点击才会生效
    view.clickWithDuration(1000) {
        //点击事件
    }
    

    上面这个例子中,实际上是通过 setTag()/getTag() 来存储 2 个扩展属性真正的值的。这是因为扩展属性并没有将实际的成员插入类中,他们只能由显示提供的 getters/setters 定义。

    2. Context的一些扩展

    在 Java 中跳转到另一个页面,一般得这样写:

    Intent intent = new Intent(context, MainActivity.class);
    context.startActivity(intent)
    

    使用 Kotlin 后我们可以这样写:

    //使用内联函数的泛型参数 reified 特性来实现
    inline fun <reified T : Activity> Context.startActivity() {
        val intent = Intent(this, T::class.java)
        if (this !is Activity) {
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        }
        startActivity(intent)
    }
    
    //这个时候跳转可以这样写,是不是特别简洁
    Context.startActivity<MainActivity>()
    

    还有很多我们常用的方法:

    //屏幕宽度(px)
    inline val Context.screenWidth: Int
        get() = resources.displayMetrics.widthPixels
        
    //屏幕高度(px)
    inline val Context.screenHeight: Int
        get() = resources.displayMetrics.heightPixels
    
    //屏幕的密度
    inline val Context.density: Float
        get() = resources.displayMetrics.density    
        
    //dp 转为 px
    inline fun Context.dp2px(value: Int): Int = (density * value).toInt()
    
    //dp 转为 px
    inline fun Context.dp2px(value: Float): Int = (density * value).toInt()
    
    //px 转为 dp
    inline fun Context.px2dp(value: Int): Float = value.toFloat() / density
    

    在实际使用时,这些方法和属性就像类本身定义的一样,我们可以直接拿来使用,非常方便,省去了类似的工具类方法调用。

    3. 可空接收者

    在 Java 中字符串操作很容易出现空指针异常,要判断一个字符串为空,一般得这样判断:

    String str = null;
    
    //对字符串 str 做是否为空判断
    if (str == null || str.length() == 0) {
    
    }
    

    在 Kotlin 中我们要判断字符串是否为空,sdk 里直接提供了一个方法 isNullOrEmpty,看源码是通过扩展来实现的,主要代码如下:

    public inline fun CharSequence?.isNullOrEmpty(): Boolean {   
        return this == null || this.length == 0
    }
    

    该方法与前面扩展函数在形式上的唯一差别是,在类型后面跟着的是?.而不是.,然后在方法体内可以通过this == null来判断调用该方法的对象是否为 null,上面的 Java 代码我们用 Kotlin 来写:

    var str = null
    //这里再也不需要额外对 str 做非空判断了,可以放心的使用了
    if (str.isNullOrEmpty()) {
    
    }
    

    使用这种方式来扩展函数,妈妈再也不用担心空指针异常了。

    4. 小结

    在 Kotlin sdk 里,可以发现它采用了大量的扩展函数。合理使用扩展,可以大量简化代码,提升开发效率,这个是 Kotlin 中我最喜欢的特性之一。

    相关文章

      网友评论

        本文标题:在Android中使用Kotlin扩展

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