浅析Kotlin——新Android官方语言

写在前面:

在不久前Google io开发者大会上面,Google突然发出大招–Kotlin成为Android开发的官方语言。一夜间,大多数全球的Android开发者们一脸懵逼,绝大多数人之前压根不知道Kotlin是个什么东西。而这就意味着,在之后的Android项目开发中将逐步从Java语言转变为Kotlin语言,而在以后新增的代码文件将不再以Java代码的形式出现,而是以 Kotlin 代码格式出现,与此同时,之前老的 Java 代码也将会陆陆续续被翻译成 Kotlin 代码。使用Kotlin语言开发Android项目的时代已经到来,本文就将从以下几个方面浅析一下这异军突起的Android官方新语言:

  • 什么是Kotlin
  • Kotlin与Java的一些比较
  • 为什么要学习Kotlin——Kotlin语言的一些特性
  • 如何在Android Studio编译器下配置Kotlin开发环境

什么是Kotlin

Kotlin是由一家位于捷克布拉格的软件开发公司JetBrains开发的基于JVM的一种语言。众所周知,该公司研发了IntelliJ IDEA这款相对于Eclipse有较大改善的大名鼎鼎IDE产品而闻名,之前有使用Java语言开发的程序猿对此应该是比较了解的。Kotlin最开始是使用Java开发者的思维被创建的,而Intellij则是作为它最主要的开发IDE。
而对于当前所有的Android开发者而言,有两个福音:

  1. 对于之前使用Java语言的Android开发者而言,Kotlin是一个非常容易学习的具有直觉化的语言,其中很大一部分和我们已知的内容是非常相似的,而一些不一样的地方,拥有着Java基础的程序猿们也可以经过短期的学习迅速掌握。
  2. Kotlin语言与我们平时所用的IDE无需配置就可以完全整合,并且我们目前来说使用最多的Android Studio能够非常完美的理解并编译运行Kotlin代码,这对于我们来说是一个非常值得开心的一件事情。

Kotlin与Java的一些比较

在Kotlin被列为Android官方语言后,很多之前一直使用Java语言开发项目的程序猿开始担心自己没有办法迅速的学习新的一门语言,并且快速的投入到实战中去。事实上,并不需要有这样的担心。尽管是已经习惯了使用Java来开发Android应用程序的开发者也不用担心,因为Java和Kotlin之间代码是可以共存的,而且更为便利的是他们之间可以相互调用,除此以外Google官方还提供了如何将Java代码转换为Kotlin代码的功能,是不是很贴心呢。

Kotlin是一种兼容Java的语言,相比于Java语言,Kotlin主要在一下几个方面具有优势:

  • 更加安全 Kotlin是空安全的,可以通过引用空指针来达到静态检测常见陷进的目的。它可以在我们编译时期就处理各种null的情况,避免了执行时异常。如果一个对象可以是null,则我们需要明确地指定它,然后在使用它之前检查它是否是null。这样就可以节约很多调试空指针异常的时间,很大程度上避免出现NullPointException。
  • 更加简洁 Kotlin在代码中很少需要在代码中指定类型,因为编译器可以在绝大多数情况下推断出变量或是函数返回值的类型。另外一个特别方便的地方是,不用写分号。对于写过脚本语言的程序猿来说,不用写分号真的是节约了很多很多时间。而Kotlin比Java更简洁的来源主要是通过支持variable type inference,higher-order functions (closures),extension functions,mixins and first-class delegation等实现的。
  • 更加具有高度互操作性 这意味着你可以继续使用你之前所有用Java写的代码和库,因为两个语言之间的互操作性是完美的,不仅可以在Kotlin代码中使用任何已有的Java库,同样地,Kotlin代码也可以为Java代码所用,即在同一个项目中可以使用Kotlin和Java两种语言混合编程。

总而言之,相比于Java有的功能,Kotlin基本上都有,而且两者之间的性能理论上是一样的,而Kotlin在一些方面则要优于Java。


为什么要学习Kotlin——Kotlin语言的一些特性

易表现(简洁性)

使用Kotlin对我们来说可以更轻易地避免模版式代码,因为大部分的典型情况都在语言中默认覆盖实现了。
举个最简单的例子,在Java中,get/set方法自动转换成属性,对应到Kotlin属性的调用。
在Java中,我们输入下段代码:

public class User {
    private int id;
    private String name;

    public void setId(int id) {
        this. id = id;
    }
    public void setName(String name) {
        this. name=name;
    }
    public int getId() {
        return id;
    }
    public String getName() {
        return name;
    }
}

说白了,上述代码就只有两个字段,一个是id,一个是name,如果我们用Kotlin来写如下:

data class User(var name: String, var id: String)

十来行变一行,有木有!!!
不仅如此,Kotlin还会自动生成所有属性和它们的访问器,以及一些方法,例如toString方法及equals方法。

var user = User("lcjingsi","0823")

空安全性

如果我们不需要参数或者只需要一个参数时

class User {
var name: String? = null
var id: String? = null

constructor(name: String) {
this.name = name
}

constructor(name: String, id: String) {
this.name = name
this.id = id
}
}

看到这里,有人会问了。String?=null 是什么意思
其实这就是我们上面所提到的Kotlin所具有的空安全性。当我们用Java写代码时,我们如果不想出现NullPointerException,那就需要我们每次在使用它之前去判断是否为空。而这个问题在 Kotlin语言中得到了很好的解决。

  • 首先可以在类型上进行处理,就是在类型后面加上?,表示这个变量或者参数及其返回值可以为null,否则就不允许为变量参数赋值为null或者返回null
  • 对于一个可能是 null 的变量或者参数,在调用对象方法或者属性之前,必须加上?,否则编译无法通过
// 这里不能通过编译,因为User不能是null
var notNullUser: User = null

// User可以是 null
var User: User? = null

// 无法编译,因为User可能是null,我们需要进行处理
artist.print()

// 只有在User != null时才会打印
User?.print()

// 如果我们在之前进行了空检查,则不需要使用安全调用操作符调用
if (User != null) {
  User.print()
}

// 只有在确保User不是null的情况下才能这么调用,否则它会抛出异常
User!!.print()

// 使用Elvis操作符来给定一个在是null的情况下的替代值
val name = User?.name ?: "empty"

就比如这段代码,如果user是可能为空的,而user没对空情况做处理,则无法编译。

我们再举个实际的例子:
Java

public void test(String string)
{
    if (string != null){
        char[]chars = string.toCharArray();
        if (chars.length>10){
               System.out.println(((Character)chars[10]).hashCode());
        }
    }
}

Kotlin

fun testNullSafeOperator(string:String?){
    System.out.println(string?.toCharArray()?.getOrNull(10)?.hashCode());
}

testNullSafeOperator(null)
testNullSafeOperator("15659766728")
testNullSafeOperator("158")

//result
null
49
null

一眼可以看出,相对于Java繁琐的判断而言,Kotlin几乎是一行代码解决问题的。

易拓展性

易拓展性就是说在Kotlin中,我们可以给任何类添加函数和方法,包括系统类以及自定义的类,这样会使得我们比项目中原本拥有的典型的工具类来的更加具有可读性。比如,我们想要在User类中添加一个toast方法:
Java

public static void toast(User user,String message){
    Toast.makeText(user,message,Toast.LENGTH_LONG).show();
}

Kotlin

fun User.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) { 
    Toast.makeText(this, message, duration).show()
}
User.toast("Hello world!")

当我们加上这段代码之后,就可以在所有用得到User的地方调用User.toast()方法。即我们只需要重写扩展方法就可以了,不过需要注意的是,如果拓展方法写到类中,只能在该类生效。

函数式

Kotlin是一种基于面向对象的语言,但是就如其他很多现代的语言一样,它使用了很多函数式编程的概念,比如使用lambda表达式来更方便地解决问题。
我们来举个简单的例子:
大家对于Android开发中经常会使用到的点击事件应该并不陌生,之前我们是这样来写的

view.setOnClickListener(new OnClickListener(){
    @Override
    public void onClick(View v) {
        Toast.makeText(v.getContext(), "Click", Toast.LENGTH_SHORT).show();
    }
})

利用刚才我们所学习到的Kotlin语言的拓展性,我们可以改写成如下形式

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

而利用lambdas表达式我们就可以把上述代码再次优化

view.setOnClickListener({view -> toast("Click")})

考虑到很多情况下我们并不需要用到参数View,所以左值参数也可以省略,考虑到只有一个参数,可以将大括号去除,于是就有了

view.setOnClickListener{toast("Click")}

比起最初的Java代码简化了差不多五倍以上,是不是很简洁,而且也特别容易理解。

Kotlin Android Extention

这个对于每一个Android应用程序开发者来说算得上是最大的福利了。也是强势推荐使用Kotlin语言来开发Android项目的重要原因。为什么这么说呢?在以往的Android开发中,大家应该都能够明显发现findViewById()是一个比较让人抓狂的函数,尽管开源界已经有几个库提供了解决办法,比如:ButterKnife,DataBinding等,但我们还是被困在这个findViewById这个让人又爱又恨的函数中。而Kotlin则是提供了一个解决该问题最简单的方法——Kotlin Android Extensions。

Kotlin Android Extensions是Kotlin的一个插件,它包含在普通的那个插件中,允许以惊人的无缝方式从Activitie,Fragment和View中恢复View,不用增加额外的代码,直接使用xml中定义的android:id就可以引用view,就像它们是在布局中定义的属性一样,你可以使用 id 的名称。除此以外它还构建本地视图缓存,因此当我们首次使用一个属性时,它会做一个普通的findViewById,而接下来,View则是从缓存中恢复,使得访问速度更快。

举个例子:
这是一个布局文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView android:id="@+id/message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</android.support.constraint.ConstraintLayout>

下面我们用两种方式写MainActivity。

  • 使用基于Kotlin语言的findViewById()方法
class MainActivity : AppCompatActivity() {
    private var mTextMessage: TextView? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        mTextMessage = findViewById(R.id.message) as TextView
        mTextMessage!!.setText("Hello jingsi")
    }
  • 利用Kotlin Android Extention插件
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    private var mTextMessage: TextView? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        message.setText("Hello jingsi");
    }

具体配置方法可参考:Kotlin编程之Kotlin Android Extensions(扩展插件)


如何在Android Studio编译器下配置Kotlin开发环境

了解到一些基础的Kotlin语言的语法和特性后,那么我们该如何在Android Studio中使用Kotlin呢?

  • 首先我们需要下载Kotlin插件(以Android Studio 3.1.2版本为例)

    点击File->Settings->Plugins 可以在已支持的插件中找到Kotlin(貌似Android Studio 3.1.2版本 是自带Kotlin插件的)

    如果使用的是老版本的Android Studio没有该插件 那么点击Install JetBrains plugins 然后在搜索栏中输入Kotlin进行搜索找到Kotlin 点击右边的Install按钮 下载完成后 Restart Android Studio即可
    这里写图片描述
    重新打开Android Studio后点击File->New 可以看到新出现的Kotlin File/Class按钮,然后点击(本来应该还有个Kotlin Activity,奈何找了很多办法也没有显示出来 好在影响不大)
    这里写图片描述

  • 然后新建Kotlin Class后会看到上方有个提示配置信息 点击Configure 进行Kotlin版本配置

这里写图片描述
这里写图片描述
点击OK,然后你会发现Android Studio自动打开了build.gradle文件,并且在头部多出了一行Kotlin的配置代码,build.gradle文件有变动,我们重新编译下项目,这时因为需要下载kotlin的相关文件,所以可能需要些时间.然后会发现project的build.gradle有了一些变化:

buildscript {
    ext.kotlin_version = '1.2.50'

    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.2'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

然后是Module下的build.gradle:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.example.lcjingsi.kotlindemo"
        minSdkVersion 15
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
sourceSets {
    main.java.srcDirs += 'src/main/kotlin'
}
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
repositories {
    mavenCentral()
}

下面我们用个简单的Demo来演示一下:
在开始写之前,我们在利用Kotlin的Kotlin-android-extensions插件的实用性,使得我们不用再写findViewById()代码配置很简单,首先在moudle的build.gradle文件头部加上这行代码:apply plugin: 'kotlin-android-extensions
这个时候我们需要重新编译下项目,然后打开MainActivity,在导包配置中,添加如下代码import kotlinx.android.synthetic.main.activity_main.*然后就可以编写代码了。

下面是activity_main.xml文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.lcjingsi.myapplication.MainActivity">

    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello Java!"
/>

    <Button
        android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello Kotlin!"
  />

    <Button
        android:id="@+id/btn3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello Android!"
  />

</LinearLayout>

然后是MainActivity

package com.example.lcjingsi.myapplication
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity(), View.OnClickListener{

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        btn1.setOnClickListener(this)
        btn2.setOnClickListener(this)
        btn3.setOnClickListener(this)
    }

    override fun onClick(v:View){
        when(v?.id){
            R.id.btn1 -> showToast("${btn1.text}")
            R.id.btn2 -> showToast("${btn2.text}")
            R.id.btn3 -> showToast("${btn3.text}")
        }
    }

    fun showToast(str:String){
        Toast.makeText(this,str,Toast.LENGTH_LONG).show();
    }
}

我们在这里实现了一个点击Button弹出Toast的效果,如下
这里写图片描述

以上就是对Google官方新推出的Android应用开发新语言Kotlin的简单介绍,当然以上只是对Kotlin进行的一个最基本的阐述和一些特性,目的是方便之前使用Java开发Android应用的程序猿们快速熟悉Kotlin,如果想要深入学习请继续阅读相关资料。

下面是一些有关Kotlin学习的资料供大家参考

Kotlin官方中文文档
Kotlin官网
Kotlin中文官网
Kotlin的gitbook网址

作者:胡静思
原文地址:https://blog.csdn.net/zuolvji1168/article/details/80721267

展开阅读全文

没有更多推荐了,返回首页