文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Kotlin 轻量级Android开发

2023-09-03 11:43

关注

Kotlin 是什么

Kotlin是一门运行在JVM之上的语言。

它由Jetbrains创建,而Jetbrains则是诸多强大的工具(如知名的Java IDE IntelliJ IDEA)背后的公司。Kotlin是一门非常简单的语言,其主要目标之一就是提供强大语言的同时又保持简单且精简的语法。
在这里插入图片描述

kotlin 特性

其主要特性如下所示:

  1. 轻量级:这一点对于Android来说非常重要。项目所需要的库应该尽可能的小。Android对于方法数量有严格的限制,Kotlin只额外增加了大约6000个方法。
  2. 互操作:Kotlin可与Java语言无缝通信。这意味着我们可以在Kotlin代码中使用任何已有的Java库;因此,即便这门语言还很年轻,但却已经可以使用成百上千的库了。除此之外,Kotlin代码还可以为Java代码所用,这意味着我们可以使用这两种语言来构建软件。你可以使用Kotlin开发新特性,同时使用Java实现代码基的其他部分。
  3. 强类型:我们很少需要在代码中指定类型,因为编译器可以在绝大多数情况下推断出变量或是函数返回值的类型。这样就能获得两个好处:简洁与安全。使用var声明可变参数,val声明不可变参数 varvar是一个可变变量,这是一个可以通过重新分配来更改为另一个值的变量。这种声明变量的方式和Java中声明变量的方式一样。 val: val是一个只读变量,这种声明变量的方式相当于java中的final变量。一个val创建的时候必须初始化,因为以后不能被改变。 上段代码: var name = "ztz" println(name) name = "yif" println(name) val finalValue = "i v"; println(finalValue); 结果如下: ztz yif iv
  4. 空安全:Java最大的一个问题就是null。如果没有对变量或是参数进行null判断,那么程序当中就有可能抛出大量的NullPointerException,然而在编码时这些又是难以检测到的。Kotlin使用了显式的null,这会强制我们在必要时进行null检查。
  5. 语法糖
    • 类的简化,隐式getter()、setter()
    • 接口的默认实现
    • lambda与高阶函数
    • 空指针安全,编译时期的空指针检查
    • 流式集合操作 map(), forEach()
  6. 新特性
    • 函数拓展、属性拓展
    • 属性代理

Kotlin 轻量级开发

Null安全

Kotlinnull安全的。如果一个类型可能为null,那么我们就需要在类型后面加上一个?。这样,每次在使用该类型的变量时,我们都需要进行null检查。比如说,如下代码将无法编译通过:

var artist: Artist? = null?artist.print()

第2行会显示一个错误,因为没有对变量进行null检查。我们可以这样做:

if (artist != null) {? artist.print()?}

这展示了Kotlin另一个出色的特性:智能类型转换。如果检查了变量的类型,那就无需在检查作用域中对其进行类型转换。这样,我们现在就可以在if中将artist作为Artist类型的变量了。这对于其他检查也是适用的。还有一种更简单的方式来检查null,即在调用对象的函数前使用?。甚至还可以通过Elvis运算符?提供另外一种做法:

val name = artist?.name ?: ""

数据类data

Java中,如果想要创建数据类或是POJO类(只保存了一些状态的类),我们需要创建一个拥有大量字段、getterssetters的类,也许还要提供toStringequals方法:

public class Artist {    private long id;    private String name;    private String url;    private String mbid;     public long getId() {        return id;    }     public void setId(long id) {        this.id = id;    }     public String getName() {        return name;    }     public void setName(String name) {        this.name = name;    }     public String getUrl() {        return url;    }     public void setUrl(String url) {        this.url = url;    }     public String getMbid() {        return mbid;    }     public void setMbid(String mbid) {        this.mbid = mbid;    }     @Override public String toString() {        return "Artist{" +                "id=" + id +                ", name='" + name + '\'' +                ", url='" + url + '\'' +                ", mbid='" + mbid + '\'' +                '}';    }}

Kotlin中,上述代码可以写成下面这样:

data class Artist (?    var id: Long,    var name: String,    var url: String,    var mbid: String)

Kotlin使用属性而非字段。基本上,属性就是字段加上其gettersetter

互操作

Kotlin提供了一些非常棒的互操作特性,这对于Android开发帮助非常大。其中之一就是拥有单个方法的接口与lambda表达式之间的映射。这样,下面这个单击监听器:

view.setOnClickListener(object : View.OnClickListener {    override fun onClick(v: View) {        toast("Click")?    }?})

可以写成这样:

view.setOnClickListener { toast("Click") }

此外,getterssetters都会自动映射到属性上。这并不会造成性能上的损失,因为字节码实际上只是调用原来的getterssetters。如下代码所示:

supportActionBar.title = titletextView.text = titlecontactsList.adapter = ContactsYifAdapter()

Lambda表达式

Lambda表达式会在极大程度上精简代码,不过重要的是借助于Lambda表达式,我们可以做到之前无法实现或是实现起来非常麻烦的事情。借助于Lambda表达式,我们可以以一种更加函数式的方式来思考问题。Lambda表达式其实就是一种指定类型,并且该类型定义了一个函数的方式。比如说,我们可以像下面这样定义一个变量:

val listener: (View) -> Boolean

该变量可以声明一个函数,它接收一个view并返回这个函数。我们需要通过闭包的方式来定义函数的行为:

val listener = { view: View -> view is TextView }

上面这个函数会接收一个View,如果该viewTextView的实例,那么它就会返回true。由于编译器可以推断出类型,因此我们无需指定。还可以更加明确一些:

val listener: (View) -> Boolean = { view -> view is TextView }

借助于Lambda表达式,我们可以抛弃回调接口的使用。只需设置希望后面会被调用的函数即可:

fun asyncOperation(value: Int, callback: (Boolean) -> Unit) {    ...    callback(true)?}asyncOperation(5) { result -> println("result: $result") }

还有一种更加简洁的方式,如果函数只接收一个参数,那就可以使用保留字it

asyncOperation(5) { println("result: $it") }

高阶函数

lambda`本身作为一等公民,它是有类型的。比如下面这个加法表达式sum的类型为`(Int, Int) -> Int。val sum: (Int, Int) -> Int = { x, y -> x+y }

一个变量有类型是再自然不过的事。而高阶函数的入参与返回值既然是lambda,那其类型奇怪一点也很正常。

fun main(args: Array<String>) {    // 自定义高阶函数, lambda 表达式 作为入参    listOf("1", "2", "3", "4").myForEach { println(it) }    // 自定义高阶函数, lambda 表达式 作为返回值//    getLogger()("I'm a Closure")    var logger = getLogger()    logger("I'm a Closure")}fun <T> List<T>.myForEach(doTask: (T) -> Unit){    for(item in this)        doTask(item)}fun getLogger(): (String) -> Unit{//    return { println(it) }    return fun (it: String){        println(it)    }}

PS: 看到getLogger()这种用法,你大概意识到可以像js那样写闭包了。

接口的默认实现

顾名思义,它便是指接口可以和抽象类一样,有方法体的默认实现。 我把它归结在语法糖里,是因为java8中早已有了一模一样的东西,对应的关键字叫default

interface A {    fun foo() { println(&quot;A&quot;) }    // 默认实现, 打印"A"    fun bar()} interface B {    fun foo() { println(&quot;B&quot;) }    fun bar() { println(&quot;bar&quot;) }} // 多继承时,显式指定 super<A>.foo() 以去冲突class D : A, B {    override fun foo() {        super&lt;A&gt;.foo()        super&lt;B&gt;.foo()    }     override fun bar() {        super.bar()    }}

流式集合操作 map(), forEach()

流式集合操作符,算是很普遍了,任何语言里都有,然而不支持函数式的话,写起来比较臃肿。 如下例子,一些操作符的衔接,使得操作逻辑十分清晰,之后需求变动,比如降序改为升序,也只需改动sortedDescending()一行,十分灵活。

fun main(args: Array&lt;String&gt;){    val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)    list.filter { it%2==0 }             // 取偶数            .map{ it*it }               // 平方            .sortedDescending()         // 降序排序            .take(3)                    // 取前 3 个            .forEach { println(it) }    // 遍历, 打印} // 输出:1006436

拓展

拓展这个东西,貌似是以装饰者模式来做的。它的效果是在不改源码的基础上,添加功能。比如我们要在Activity上加一个toast(),完全不用卸载基类里。这样简化了很多工作,尤其是对一些已打成jar包的类。

fun Activity.toast(msg: String) {    Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()}fun main(args: Array&lt;String&gt;) {    val list = listOf(&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;)     // 函数拓展    list.myForEach { println(it) }     // 属性拓展    println(&quot;last: ${list.lastItem}&quot;)} fun &lt;T&gt; List&lt;T&gt;.myForEach(doTask: (T) -&gt; Unit){    for(item in this)        doTask(item)} val &lt;T&gt; List&lt;T&gt;.lastItem: T        get() = get(size - 1) // 输出:1234last: 4

属性代理

它把属性的get()set()代理给了一个类,以便可以在get()set()时做一些额外的操作。如:

来源地址:https://blog.csdn.net/hdbdhdbh/article/details/131286043

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯