Android开发: 分享如何利用好Kotlin的特点(二)---- 优化你的代码

297 阅读2分钟

Kotlin的扩展函数

Kotlin的扩展函数,在日常Android开发中经常用到,当然前提你使用Kotlin来开发,之前有次和同事聊天我说完这句话,他说:他都不用这些,因为他只用Java开发。我:emmm.. 对~!你说得对。 举几个我们常见的,已经写好了给我们直接用的:

@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}

@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    return this
}

public inline fun String.filter(predicate: (Char) -> Boolean): String {
    return filterTo(StringBuilder(), predicate).toString()
}

有了官方给我们的这些那么好用的扩展函数,的确能很好地减少我们的代码量,如下:

 val stringTo20 = "20"
 Log.e(TAG, "value:${stringTo20.toInt()}")
 

 E/MainActivity: value:20

点击这个toInt() 方法,进去看看就是经常用到的字符串转数字方法

@kotlin.internal.InlineOnly
public actual inline fun String.toInt(): Int = java.lang.Integer.parseInt(this)

但是如果我们写成这样呢?Crash是必然的了

 val stringTo20 = "www"
 Log.e(TAG, "value:${stringTo20.toInt()}")
 
 java.lang.NumberFormatException: For input string: "www"

当然,如果那个字符串是正常的数字字符串,那我们的代码的确直接用toInt(),但是,凡事都有例外,假如有个需求是你要从后台获取一个“数字”字符串,不要问我问什么不直接用json,我举例子而已,然后突然某天配置错了然后配了个不是纯数字的, 而你又忘了try catch 直接 toInt(),不要问我为什么网络请求不处理这种异常,我举例子而已。
开发(不知道配置错了):呃,你手机中毒了?怎么App闪退了。
那我们平时开发是不是应该尽力去避免这种情况呢?


 val stringTo20 = "www"
 fun String.forceToInt(default: Int = 0) : Int {
        return if(this.filter { it.isDigit() }.any { this.isNotEmpty() }){
            toInt()
        }else{
            default
        }
    }
 Log.e(TAG, "value:${stringTo20.forceToInt(-1)}")

我们可以利用扩展函数处理这种情况,简单又方便。

Kotlin的infix函数

这个infix符号修饰的是中缀函数,我们多用于修饰扩展函数,记得有且只有一个参数
举应用MutableLiveData作为例子

infix fun <T:Any> MutableLiveData<T>?.post(newValue:T){
    this?.postValue(newValue)
}

infix fun <T:Any> MutableLiveData<T>?.set(newValue:T){
    this?.value = newValue
}

//可以直接使用变成
(MutableLiveData) data   post  newValue
(MutableLiveData) data   set  newValue

这种方法并不会带来什么性能上的优化,代码相比 .执行方法显得直观,特别是用于数字计算或者合并某些内容等等,切勿乱起名字,否则会很难拿维护,尽量保证名字能和功能相关
如下:

button translationX 200f
infix fun View.translationX(float: Float){
        translationX = float
    }
    
//如果像这样,很难有第一反应是translationX,我会以为是view.x = float    
 button toX 200f
 infix fun View.toX(float: Float){
        translationX = float
    }

未完,后续更新