• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Kotlin开发中的一些Tips

android 搞代码 3年前 (2022-03-01) 12次浏览 已收录 0个评论

作用域函数抉择

目前有letrunwithapply 和 also五个作用域函数。

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

 总结一下有几点区别:

1、applyalso返回上下文对象。

2、letrun 和with返回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'
    ]
}

相干视频:

【2021最新版】Android studio装置教程+Android(安卓)零基础教程视频(适宜Android 0根底,Android初学入门)含音视频_哔哩哔哩_bilibili

Android进阶学习:Kotlin核心技术_哔哩哔哩_bilibili

【Android进阶课程】——colin Compose的绘制原理解说(一)_哔哩哔哩_bilibili

【 Android进阶教程】——Framework面试必问的Handler源码解析_哔哩哔哩_bilibili

【 Android进阶教程】——热修复原理解析_哔哩哔哩_bilibili

【 Android进阶教程】——如何解决OOM问题与LeakCanary原理解析_哔哩哔哩_bilibili


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Kotlin开发中的一些Tips

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址