Kotlin开发总结

作者: 十思叶 | 来源:发表于2018-06-24 18:28 被阅读189次

    纲要


    1. 前言
    2. Kotlin是什么?
    3. 为什么使用Kotlin?
    4. Kotlin常用特性有哪些?
    5. 如何在开发中使用Kotlin?
    6. 使用Kotlin常见问题有哪些?

    前言


    从2017年秋季接触Kotlin以来,开始3个月写了一些学习Demo,最近半年才开始用Kotlin开发企业级的APP,遇到了一点坑,但整体感觉:简洁、高效,以至于现在丝毫不想写又臭又长的Java代码。
    还在坚持写Java的同学不妨试试Kotlin,一定会让你流连忘返、乐不思Java ,:p。

    Kotlin是什么?


    简介
    Kotlin是一种在Java虚拟机上运行的静态类型编程语言,它也可以被编译成为JavaScript源代码。
    主要由JetBrains的圣彼得堡团队所开发,其名称来自于圣彼得堡附近的科特林岛。

    静态动态类型编程语言:通俗讲
    静态类型指的是编译器在compile time执行类型检查,动态类型指的是编译器(虚拟机)在runtime执行类型检查

    应用范围

    适用构建Kotlin应用的平台(引自官网)

    JVM-Java服务端开发(替代Java?)
    Android
    Browser-JavaScript开发(替代JavaScript?)
    Native-C相关开发(替代C、Object-C和Swift?)

    历史

    Kotlin历史版本

    • 2011年7月-JetBrains推出Kotlin项目
    • 2016年2月-发布v1.0版本
    • 2017年11月28日-v1.2
    • 2018年6月14日-v1.2.50

    Google支持情况

    为什么使用Kotlin?


    通用理由

    引自官网中文站

    参考示例见官方
    https://www.kotlincn.net/

    使用Kotlin开发Android的理由

    • 兼容性:Kotlin 与 JDK 6 完全兼容,保障了 Kotlin 应用程序可以在较旧的 Android 设备上运行而无任何问题。Kotlin 工具在 Android Studio 中会完全支持,并且兼容 Android 构建系统。
    • 性能:由于非常相似的字节码结构,Kotlin 应用程序的运行速度与 Java 类似。 随着 Kotlin 对内联函数的支持,使用 lambda 表达式的代码通常比用 Java 写的代码运行得更快。
    • 互操作性:Kotlin 可与 Java 进行 100% 的互操作,允许在 Kotlin 应用程序中使用所有现有的 Android 库 。这包括注解处理,所以数据绑定和 Dagger 也是一样。
    • 占用:Kotlin 具有非常紧凑的运行时库,可以通过使用 ProGuard 进一步减少。 在实际应用程序中,Kotlin 运行时只增加几百个方法以及 .apk 文件不到 100K 大小。
    • 编译时长:Kotlin 支持高效的增量编译,所以对于清理构建会有额外的开销,增量构建通常与 Java 一样快或者更快
    • 学习曲线:对于 Java 开发人员,Kotlin 入门很容易。包含在 Kotlin 插件中的自动 Java 到 Kotlin 的转换器有助于迈出第一步。Kotlin 心印 通过一系列互动练习提供了语言主要功能的指南。

    另外的理由

    1. 不用写烦人的findViewById
    2. Android Studio支持Java To Kotlin一键转换

    Kotlin常用特性有哪些?


    具体语法可见Kotlin官网,或对应的中文版
    以下主要说一下常用的语法或特性

    基本语法

    定义变量

        fun testDefination() {
            // 不可变
            val a: Int = 1  // 立即赋值
            val b = 2   // 自动推断出 `Int` 类型
            val c: Int  // 如果没有初始值类型不能省略
            c = 3       // 明确赋值
    
            // 可变
            var x = 5 // 自动推断出 `Int` 类型
            x += 1
        }
    
    class KotlinSyntax {
        data class Person(val name: String, val age: Int, val isMale: Boolean,
                          var address: String? = "")
        // 懒加载
        private val freshman by lazy {
            Person("feifei", 18, true)
        }
        // 延迟加载。定义成员变量时必须初始化,但不想初始化或不想引入空时,可以使用延迟加载
        private lateinit var old: Person
    }
    

    字符串模板

        @Test fun testStringTemplates() {
            val age = 12
            val name = "feifei"
            print("name -> $name, age -> $age")
        }
    

    Elvis 操作符?

        // 判空。如果str=null,会打印:Length = null
        @Test fun testNull (str: String?) {
            println("Length = " + str?.length)
        }
    
        // 类型转换
        @Test fun testCast() {
            val l2 = listOf("A",1,3,6,8,'c')
            l2.forEach { println(it as? Int) }
        }
    

    断言操作符!!

        private var p1: Person? = null
        @Test
        fun testAssert() {
            p1 = Person("feifei", 18, true)
            println(p1!!.name)
        }
    

    条件表达式

        @Test
        fun testCondition() {
            // 空条件
            val files = File("Test").listFiles()
            println(files?.size ?: "empty")
    
            // if-else
            println("max -> ${maxOf(1,2)}")
            
            // when
            val items = listOf("apple", "banana", "kiwifruit", "grape", "pear", "ab...")
            when {
                "orange" in items -> println("juicy")
                "apple" in items -> println("apple is fine too")
            }
            
            // when
            describe(items[0])
        }
    
        fun maxOf(a: Int, b: Int): Int {
            return if (a > b) {
                a
            } else {
                b
            }
        }
    
        fun describe(obj: Any): String =
                when (obj) {
                    1 -> "One"
                    "Hello" -> "Greeting"
                    is Long -> "Long"
                    !is String -> "Not a string"
                    else -> "Unknown"
                }
    

    循环表达式和集合

        @Test
        fun testLoop() {
            val items = listOf("apple", "banana", "kiwifruit", "grape", "pear", "ab...")
            // for loop
            testForLoop(items)
            // collection
            testCollection(items)
        }
    
        private fun testForLoop(items: List<String>) {
            for (item in items) {
                println(item)
            }
            for (index in items.indices) {
                println("item at $index is ${items[index]}")
            }
            for (index in 0 until items.size) {
                println("item at $index is ${items[index]}")
            }
            for (index in items.size - 1 downTo 0 step 2) {
                println("item at $index is ${items[index]}")
            }
        }
    
        private fun testCollection(items: List<String>) {
            items.filter { it.startsWith("a") }
                    .sortedBy { it }
                    .map { it.toUpperCase() }
                    .forEach { println(it) }
        }
    

    类型检测

    fun getStringLength(obj: Any): Int? {
        if (obj is String) {
            // `obj` 在该条件分支内自动转换成 `String`
            return obj.length
        }
    
        // 在离开类型检测分支后,`obj` 仍然是 `Any` 类型
        return null
    }
    

    默认参数

        @Test
        fun testDefaultArgs() {
            println(createPerson("feifei1"))
            println(createPerson("feifei2", 12))
            println(createPerson("feifei3", 12, true))
        }
    
        private fun createPerson(name:String, age:Int = 0, isMale: Boolean = false):Person {
            return Person(name, age, isMale)
        }
    

    数据模型

        // 会为 Customer 类提供以下功能:
        // 所有属性的 getters (对于 var 定义的还有 setters)
        // equals()/hashCode()/toString()/copy()等
        data class Customer(val name: String, val email: String)
    

    单例

        object Resource {
            val name = "Name"
        }
    

    常量

    class KotlinSyntax {
        companion object {
            const val PI = 3.14
        }
    }
    
    // 或者
       object Resource {
            val name = "Name"
            const val PI = 3.14
        }
    

    方法作为其他方法的参数
    一般用于回调

    // 场景,有一个轮播条,点击其中一个进入详情
    // 定义一个adapter,传入值和对调函数
    class BannerPagerAdapter (var srcs: List<String>,
                              private val callback: (position: Int)->Unit) : PagerAdapter() {
        override fun instantiateItem(container: ViewGroup, position: Int): Any {
            val view = LayoutInflater.from(container.context).inflate(R.layout.view_home_headline, container, false)
            val tvHeard = view.findViewById<TextView>(R.id.iv_headline)
            // 设置点击监听
            tvHeard.setOnClickListener({callback(srcs[position])})
            container.addView(view)
            return view
        }
        // ...
    }
        
        // 在Activity中设置
        private val bannerAdapter by lazy {
            BannerPagerAdapter(list_banner, callback = { title ->
                toBannerDetail(title)
            })
        }
    
        private fun toBannerDetail(title: String) {
            // to detail
        }
    
    
    

    范围外 run,let,with,apply

    class Turtle {
            fun penDown(){}
            fun penUp(){}
            fun turn(degrees: Double){}
            fun forward(pixels: Double){}
        }
    
        // 对一个对象实例调用多个方法 (with)
        @Test
        fun testWith() {
            val myTurtle = Turtle()
            with(myTurtle) { // 画一个 100 像素的正方形
                penDown()
                for(i in 1..4) {
                    forward(100.0)
                    turn(90.0)
                }
                penUp()
            }
        }
    

    Java调用Kotlin

        public void useKotlin() {
            // use object
            System.out.print(KotlinObject.PI);
            System.out.print(KotlinObject.INSTANCE.max(1,2));
            
            // use class static const or fun
            System.out.print(KotlinClass.PI);
            System.out.print(KotlinClass.Companion.max(1,2));
        }
    

    用于Android开发的工具

    • Kotlin Android 扩展是一个编译器扩展, 可以让你摆脱代码中的 findViewById() 调用,并将其替换为合成的编译器生成的属性。
    • Anko 是一个提供围绕 Android API 的 Kotlin 友好的包装器的库 ,以及一个可以用 Kotlin 代码替换布局 .xml 文件的 DSL。

    如何在开发中使用Kotlin


    非Android开发

    请见官方文档,或对应中文版

    Android开发

    创建新项目
    Android Studio 3.0+完全支持kotlin,创建项目的时候,默认勾选支持Kotlin,创建完项目后会自动在gradle文件中引入插件和扩展插件。

    Android Studio 3.0+创建新项目

    创建完工程后,工程gradle文件中


    工程gradle文件

    应用Module gradle文件中


    应用Module gradle文件

    Java 转 Kotlin

    1. 切到要转换的Java文件
    2. Android Studio菜单 Code -> ‘Convert Java File to Kotlin File’, 或 Mac环境下,双击Shite键,输入 covert java....出现‘Convert Java File to Kotlin File’选项。

    Java转kotlin的常见问题
    一般而言可以直接转换,无需修改,但有时需要手动修改,一般在如下几个地方出现:

    1. 逻辑操作符。kotlin中只有Int类型的值才能直接进行逻辑运算,其他类型如Byte要转为Int之后才能进行逻辑运算。且,kotlin中的逻辑运算是作为方法出现的。

      逻辑运算 Java vs Kotlin
    2. 单行赋值后进行比较
      这个在读流操作时经常出现

        private void readIS(InputStream is) throws Exception {
            int len = 0;
            byte[] bytes = new byte[1024];
            OutputStream os = new FileOutputStream("/file/text.txt");
            while ((len = is.read(bytes)) != -1) {
                os.write(bytes, 0, len);
            }
        }
    

    直接转换成kotlin是

       @Throws(Exception::class)
        private fun readIS(`is`: InputStream) { // is是kotlin关键字,所有做了处理
            var len = 0
            val bytes = ByteArray(1024)
            val os = FileOutputStream("/file/text.txt")
            while ((len = `is`.read(bytes)) != -1) {  // 这行报语法错误
                os.write(bytes, 0, len)
            }
        }
    
    // 稍作修改,消除语法错误
        @Throws(Exception::class)
        private fun readIS(`is`: InputStream) {
            var len = 0
            val bytes = ByteArray(1024)
            val os = FileOutputStream("/file/text.txt")
            len = `is`.read(bytes)
            while (len != -1) {
                os.write(bytes, 0, len)
                len = `is`.read(bytes)
            }
        }
    

    使用Kotlin常见问题有哪些?


    待续

    参考


    Kotlin官网
    Kotlin中文网
    Android开发者官方
    Android Kotlin Guides

    相关文章

      网友评论

      本文标题:Kotlin开发总结

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