kotlin频道Kotlin开发知识Kotlin学习

Android必备技能之一:Kotlin(一)

2017-03-10  本文已影响1129人  罗罗罗罗罗sky
20161105_161848.jpg

1、Kotlin前世与今生

那么我们可以一起来尝试一下 Kotlin,话说回来了什么是Kotlin呢?

Kotlin是基于JVM新的编程语言,由 JetBrains 开发,可以编译成java字节码,也可以编译成JavaScript。而JetBrains,作为目前广受欢迎的Java IDE IntelliJ 的提供商,也在 Apache 许可下已经开源其Kotlin 编程语言。

2、Kotlin环境配置

接下来的我就直接在Android Studio(下面简称AS)环境上面操作,虽然使用IDE IntelliJ也可以实现,但AS上也是对Kotlin支持的,首先下载以下相关插件(虽然并不是所有插件一次性用到,但建议一次性下载完,后续就不需要下载了):

其中Anko DSL Preview插件用于预览使用DSL编写的UI代码,就像以前使用xml编写UI文件时可以动态在“Preview”窗口预览效果一样。

上面三个插件下载安装重启之后,然后新建一个项目默认配置Gradle如下:

    ext.kotlin_version = '1.1.0'
    ext.anko_version = '0.8.2'
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
    }
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

.........................

dependencies {
    .........................
    
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
    compile "org.jetbrains.anko:anko-sdk15:$anko_version"
    compile "org.jetbrains.anko:anko-support-v4:$anko_version"
    .........................
}
repositories {
    mavenCentral()
}

这里添加了Kotlin对android的扩展,同时也添加了Kotlin的gradle插件。我们打开系统默认帮我们建的MainActivity,然后Code->Convert Java File to Kotlin File->OK,此时我们原有的Activity应该将我们转换成了如下内容:

class KoTlinActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_ko_tlin)
    }
}

上面这一步是将java代码转换为Kotlin代码。截止到现在,你什么都不用做,程序就已经可以跑起来了。你可能要说代码相比之下并没有简洁多少啊 ,当然到这里并没有结束,反而是开始,只是首先一起来体验下我们的第一个Kotlin代码程序。

3、Kotlin完美给Java开发者打造

3.1 通用的集合框架和Kotlin的扩展

通用的集合框架,ex如下:

  val list = arrayListOf(1, 2, 3, 4)
        list.add(5)
        list.remove(3)
        for (item in list) {
            debug(item);
        }

效果如下:

03-09 16:06:23.991 21108-21108/com.Igeek.kotlin D/MainActivity: 1
03-09 16:06:23.991 21108-21108/com.Igeek.kotlin D/MainActivity: 2
03-09 16:06:23.991 21108-21108/com.Igeek.kotlin D/MainActivity: 4
03-09 16:06:23.991 21108-21108/com.Igeek.kotlin D/MainActivity: 5

可以看到这里Kotlin写法和java是差不多的。

至于Kotlin的扩展,其实就是对java的库进行了进一步扩展,ex如下:

 val list = arrayListOf(1, 2, 3, 4, 5)
        list.forEach {
            debug(it)
        }
        debug("==========================")
        val doubleList = list.map {
            it * 2
        }
        doubleList.forEach {
            debug(it)
        }
        debug("==========================")
        val oddList = list.filter{
            it % 2 == 1
        }
        oddList.forEach {
            debug(it)
        }

打印如下:

03-09 16:18:06.978 28828-28828/com.Igeek.kotlin D/MainActivity: 1
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 2
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 3
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 4
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 5
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: ==========================
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 2
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 4
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 6
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 8
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 10
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: ==========================
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 1
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 3
03-09 16:18:06.979 28828-28828/com.Igeek.kotlin D/MainActivity: 5

3.1 Kotlin与Java的交互

Kotlin的标准库更多的是对Java库的扩展,基于这个设计思路,你丝毫不需要担心Kotlin对Java代码的引用,你甚至可以在Kotlin当中使用Java反射,反正只要是Java有的,Kotlin都有。最常见的就是Getter/Setter方法对应到Kotlin属性的调用,ex如下:
首先准备一个java类:

8208E5B2-6AA0-4F0F-BA2D-A1F067D08DCC.png

调用如下:

       val javaPerson = Person()
        javaPerson.address = "Wo shi Kotlin"
        debug(javaPerson.address)

打印结果就是"Wo shi Kotlin"了,刚刚只顾着写,忘了提一句,在Kotlin语法里面,是不用在后面加“;”的,有没有感觉很爽,废话不说了,可以看到我们调用时候,既没有用到get方法也没有用到set方法,是不是避免了总会有人说get/set方法影响性能的问题。
官网地址(有详细的比较):https://kotlinlang.org/docs/reference/java-interop.html#static-methods-and-fields

4、简洁 可靠 有趣

4.1数据类

在JavaBean中我们往往会覆写诸如equals和hashcode等方法,一旦用到HashMap这样的集合框架,总是出了问题都不知道找谁。Kotlin提供了一种非常简单的方式来创建这样的数据类,ex如下:

data class Main(val id:Int,val name:String)

//main方法调用
fun main(args:Array<out String>){
    println(Main(0,"Main函数"))
}

打印结果:

Main(id=0, name=Main函数)

仅仅一行代码,Kotlin就会创建出一个完整的数据类,并自动生成相应的equals、hashcode、toString方法。

4.2 空安全与属性代理

想想平时QA提的bug,不太靠谱的server,不太确定数据类型,均可能出现Exception,但我们总不能在所有地方都进行判断,第一次看到Kotlin的空安全处理,真的眼前一亮。
Kotlin的空安全设计,主要是在类型后面加?表示可空,否则就不能为null,ex如下:

val nullable: Int? = 0
val nonNullable: Int = 2
nullable.toFloat() // 编译错误
nullable?.toFloat() // 如果null,什么都不做,否则调用toFloat
nullable!!.toFloat() // 强制转换为非空对象,并调用toFloat;如果nullable为null,抛空指针异常
nonNullable.toFloat() // 正确

我们利用Convert Java File to Kotlin File生成的Kotlin代码,在onCreate方法中也是如此考虑,savedInstanceState是否为空。

override fun onCreate(savedInstanceState: Bundle?) {}

注:这里的空指针异常是KotlinNullPointerException,而不是Java的NullPointerException。

5、Kotlin场景使用

好了,接下来我们就实战说说Kotlin的用法,用如下代码举例:
java代码:

8F167006-EA0F-4D14-BE9B-20BA6562DDEA.png

Kotlin代码:

46EA6401-2A70-40FA-91A5-9EAA38E76670.png

5.1 场景一(控件findViewById)

findViewById有很多写法,我们就从复杂到容易说起:

写法一:

      private var tv_hello_view: TextView? = null
         .......................................
        tv_hello_view = findViewById(R.id.tv_hello_view) as TextView
        tv_hello_view!!.text = "Say Hello!!!"
        tv_hello_view!!.textSize = 22f
        tv_hello_view!!.setOnClickListener {}

有没有发现写法一还不如java写法,貌似java写法还简单一点,并且设置text和size时候,需要加两个叹号,不加的话貌似编译器并不识别你是否为null,下面我们来看写法二:

写法二:

   private val  tv_hello_view: TextView by lazy{
        findViewById(R.id.tv_hello_view) as TextView
    }
   .......................................
        tv_hello_view.text = "Say Hello!!!"
        tv_hello_view.textSize = 22f
        tv_hello_view.setOnClickListener {}

这种写法好像简单了一点,不过好像依然很复杂,注意在这里初始化的时候不要直接

private var tv_hello_view: TextView  //编译错误

lazy是Kotlin的属性代理的一个实例,它提供了延迟加载的机制。换句话说,这里的lazy提供了初始化aTextView的方法,不过真正初始化这个动作发生的时机却是在aTextView第一次被使用时了。lazy默认是线程安全的,你当然也可以关掉这个配置,只需要加个参数LazyThreadSafetyMode.NONE即可:

private val tv_hello_view: TextView by lazy(LazyThreadSafetyMode.NONE){
     findViewById(R.id.tv_hello_view) as TextView
}

写法三:

private lateinit var tv_hello_view: TextView
   .......................................
        tv_hello_view = findViewById(R.id.tv_hello_view) as TextView
        tv_hello_view.text = "Say Hello!!!"
        tv_hello_view.textSize = 22f
        tv_hello_view.setOnClickListener {}

这里主要用了lateinit 来修饰它,方法简单了不少吧 ,但是findViewById这个单词好长啊,能不能简化啊,答案是肯定的,我们请出Anko,注意我们有依赖过dependencies哟。

写法四:

private lateinit var tv_hello_view: TextView
   .......................................
        tv_hello_view = find(R.id.tv_hello_view) 
        tv_hello_view.text = "Say Hello!!!"
        tv_hello_view.textSize = 22f
        tv_hello_view.setOnClickListener {}

可以看到我们方法改成了find,并且没了 as TextView,注意我们需要import org.jetbrains.anko.find。既然请出来了Anko ,那么我们还有终极方案,完全去除findViewById。

写法五:

CD9648CF-79D0-48FB-AED7-59A2CAAF448B.png

可以发现直接操作tv_hello_view,这便是findViewById的终极写法。
注:

1.导入了import kotlinx.android.synthetic.main.hello_layout.*包
2. tv_hello_view是hello_layout布局xml中的id

写到这里,内容也挺多了,我也只是把用法统一归纳一下,至于findViewById所牵扯出来的几个点:lazy,primitives, lateinit, Anko以及不要 findViewById仍然能找到控件的原理我并没有去细致分析,后续有时间我会再补充上,当然如果想更多的去了解,可以有一下资料参考:

Kotlin官网文档地址:https://kotlinlang.org/docs/
《Kotlin for android Developers》中文翻译: https://github.com/wangjiegulu/kotlin-for-android-developers-zh/blob/master/SUMMARY.md

在这里推荐一部Kotlin基础学习视频:https://pan.baidu.com/s/1b2tBH0 提取码:nryk

本博客参考了一下文献:
Kotlin for android Developers》中文翻译;
博客:http://www.println.net/post/Android-A-Powerful-Substitution-Kotlin
博客:http://mp.weixin.qq.com/s?__biz=MzIzMTYzOTYzNA==&mid=100000121&idx=1&sn=6a8c4b27dec4e03a58e888c5fa18b7e2&chksm=68a05e445fd7d752da50717bec037f51702aa9557b308114f2d7255109509bcd24c1a5d80903&mpshare=1&scene=23&srcid=0309PegdxPNifENVckrvhBZY#rd

上一篇下一篇

猜你喜欢

热点阅读