关于android:Kotlin开发中的一些Tips

45次阅读

共计 3699 个字符,预计需要花费 10 分钟才能阅读完成。

作用域函数抉择

目前有 letrunwithapplyalso 五个作用域函数。

官网文档有张表来阐明它们之间的区别:

总结一下有几点区别:

1、applyalso 返回上下文对象。

2、letrunwith 返回lambda 后果。

3、letalso援用对象是it,其余是this

1.letrun 是我日常应用最多的两个,它们之间很相似。

private var textView: TextView? = null

textView?.let {
    it.text = "Kotlin"
    it.textSize = 14f
}

textView?.run {
    text = "Kotlin"
    textSize = 14f
}

相比拟来说应用 run 显得比拟简洁,但 let 的劣势在于能够将 it 重命名,进步代码的可读性,也能够防止作用域函数嵌套时导致混同上下文对象的状况。

2. 对于可空对象,应用 let 比拟不便。对于非空对象能够应用with

3.applyalso 也十分类似,文档给出的倡议是如果是对象配置操作应用apply,额定的解决应用also。例如:

val numberList = mutableListOf<Double>()
numberList.also {println("Populating the list") }
    .apply {add(2.71)
        add(3.14)
        add(1.0)
    }
    .also {println("Sorting the list") }
    .sort()

简略说就是合乎单词的含意应用,进步代码可读性。

总的来说,这几种函数有许多重叠的局部,因而能够依据开发中的具体情况来应用。以上仅做参考。

Sequence

咱们常常会应用到 kotlin 的汇合操作符,比方 map 和 filter 等。

list.map {it * 2}.filter {it % 3 == 0}

老规矩,看一下反编译后的代码:

就干了这么点事件,创立了两个汇合,循环了两遍。效率太低,这还不如本人写个 for 循环,一个循环就解决完了。看一下 map 的源码:

public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}

public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapTo(destination: C, transform: (T) -> R): C {for (item in this)
        destination.add(transform(item))
    return destination
}

外部实现的确如此,难道这些操作符不香了?

其实这时就能够应用 Sequences(序列),用法很简略,只须要在汇合后增加一个asSeqence() 办法。

list.asSequence().map {it * 2}.filter {it % 3 == 0}

反编译:

SequencesKt.filter(SequencesKt.map(CollectionsKt.asSequence((Iterable)list), (Function1)null.INSTANCE), (Function1)null.INSTANCE);

有两个 Function1,其实就是 lambda 表达式,这是因为 Sequence 没有应用内联导致的。咱们先看看 SequencesKt.map 源码:

public fun <T, R> Sequence<T>.map(transform: (T) -> R): Sequence<R> {return TransformingSequence(this, transform)
}

internal class TransformingSequence<T, R>
constructor(private val sequence: Sequence<T>, private val transformer: (T) -> R) : Sequence<R> {override fun iterator(): Iterator<R> = object : Iterator<R> {val iterator = sequence.iterator()
        override fun next(): R {return transformer(iterator.next())
        }

        override fun hasNext(): Boolean {return iterator.hasNext()
        }
    }

    internal fun <E> flatten(iterator: (R) -> Iterator<E>): Sequence<E> {return FlatteningSequence<T, R, E>(sequence, transformer, iterator)
    }
}

能够看到没有创立两头汇合去循环,只是创立了一个 Sequence 对象,外面实现了迭代器。SequencesKt.filter办法也是相似。仔细的话你会发现,这都只是创立 Sequence 对象,所以要想真正拿到解决后的汇合,须要增加 toList()这种末端操作。

map 和 filter 这类属于两头操作,返回的是一个新 Sequence,外面有数据迭代时的理论解决。而 toList 和 first 这类属于末端操作用来返回后果。

所以 Sequence 是提早执行的,这也就是它为何不会呈现咱们一开始提到的问题,一次循环就解决实现了。

总结一下 Sequence 的应用场景:

1、有多个汇合操作符时,倡议应用 Sequence。

2、数据量大的时候,这样能够防止反复创立两头汇合。这个数据量大,怎么也是万以上的级别了。

所以对于个别 Android 开发中来说,不应用 Sequence 其实差异不大。。。哈哈。。

协程

有些人会谬误了解 kotlin 的协程,感觉它的性能更高,是一种“轻量级”的线程,相似 go 语言的协程。然而如果你细想一下,这是不太可能的,最终它都是要在 JVM 上运行,java 都没有的货色,你就实现了,你这不是打 java 的脸嘛。

所以对于 JVM 平台,kotlin 的协程只能是对 Thread API 的封装,和咱们用的 Executor 相似。所以对于协程的性能,我集体也认为差异不大。只能说 kotlin 借助语言简洁的劣势,让操作线程变的更加简略。

之所以下面说 JVM,是因为 kotlin 还有 js 和 native 平台。对于它们来说,或者能够实现真正的协程。

举荐扔物线大佬对于协程的文章,帮你更好的了解 kotlin 的协程:到底什么是「非阻塞式」挂起?协程真的更轻量级吗?

Checked Exception

这对相熟 Java 的同学并不生疏,Checked Exception 是解决异样的一种机制,如果你的办法中申明了它可能会抛出的异样,编译器就会强制开发者对异样进行解决,否则编译不会通过。咱们须要应用 try catch 捕捉异样或者应用 throws 抛出异样解决它。

然而 Kotlin 中并不反对这个机制,也就是说不会强制你去解决抛出的异样。至于 Checked Exception 好不好,争议也不少。这里就不探讨各自的优缺点了。

既然 Kotlin 中没有这个机制曾经是既成事实,那么咱们在应用中就须要思考它带来的影响。比方咱们开发中在调用一些办法时,要留神看一下源码中是否有指定异样抛出,而后做相应解决,防止不必要的解体。

例如罕用的 json 解析:

private fun test() {val jsonObject = JSONObject("{...}")
    jsonObject.getString("id")
    ...
}

在 java 中咱们须要解决JSONException,kotlin 中因为没有 Checked Exception,如果咱们像下面这样间接应用,尽管程序能够运行,可是一但解析出现异常,程序就会解体。

Intrinsics 查看

如果你常常察看反编译后的 java 代码,会发现有许多相似 Intrinsics.checkXXX 这样的代码。

fun test(str: String) {println(str)
}

反编译:

比方图中的 checkParameterIsNotNull 就是用了查看参数是否为空。尽管咱们的参数是不可控的,然而思考到办法会被 Java 调用,Kotlin 会默认的减少 checkParameterIsNotNull 校验。如果 kotlin 办法是公有的,也就不会有此行查看。

checkParameterIsNotNull并不会有性能问题,相同这种提前判断参数是否正确,能够防止程序向后执行导致不必要的资源耗费。

当然如果你想去除它,能够增加上面的配置到你的 gradle 文件,这样就会在编译时去除它。

kotlinOptions {
    freeCompilerArgs = [
            '-Xno-param-assertions',
            '-Xno-call-assertions',
            '-Xno-receiver-assertions'
    ]
}

本文转自 https://blog.51cto.com/u\_15376247/4759943,如有侵权,请分割删除。

正文完
 0