Kotlin

Posted on By Vivian Sun

Kotlin简介

Google IO 2017宣布了 Kotlin 会成为 Android 官方开发语言。一时间朋友圈和Android圈被各种刷屏。

眼下Android圈已经躁动了,甚至严重到如果对Kotlin视而不见就显得自己不像一个合格的Android程序员。

Kotlin的有很多特点,比如简洁,安全实用,开发效率高和提升可读性,更好的函数式编程支持。

  1. 简洁,Kotlin的代码确实比Java更加简洁,比如类型推断,省去结尾的分号等等,然而这远不能成为我们改用Kotlin的原因。

  2. 安全,这是Kotlin的一个很重要的特性。Kotlin是空指针安全的,JetBrains做了一件很聪明的事情,它们将运行时才能空指针的检测提前到了编译时,主要方式是增加了Any?这种可为空的类型,使用Kotlin之后,我们程序的空指针会得到明显的改善。

  3. 实用,高效率。Kotlin的实用具体表现在

  • 引入Object,便于我们更好的应用单例模式
  • 引入data class, 避免了我们手写getter/setter/toString等方法
  • 引入参数默认值和具名参数,避免了不必要的方法重载
  • 支持扩展方法,让我们可以省去好多必须要的代码
  1. Kotlin引入了Lambda,Streams API 和函数式编程支持。
  • Lambda表达式可以省去了我们创建很多匿名内部类的代码(注由于目前Kotlin基于JVM6,Lambda表达式在字节码阶段依然会翻译成内部类形式)
  • Streams API 结合Lambda表达式和方法引用,让我们的代码处理一件事情以描述的形式,而不是命令实现的方式。
  • Kotlin支持OOP(面向对象编程)和FP(函数式编程),语言本身并没有限制,给了我们选择的自由,Kotlin对FP的友好支持,便于我们写出更加稳定,易于测试,无副作用的方法和代码
  1. 可读性 从客观上,Kotlin语法和特性上让代码更加具有描述性而已。但是不得不指出代码可读性主要依赖编写者的编码素质和能力。

学习Kotlin吗?

介绍Kotlin学习的必要性

Kotlin之旅

介绍Kotlin的实践使用

书籍

  • kotlin-docs
  • kotlin-in-action-in-chinese

下载地址

Kotlin 实践

AS 版本2.3.3

  1. AS安装Kotlin插件 Settings -> Plugins 搜索Kotlin(download最多的那个)

    Kotlin language support Vendor JetBrains s.r.o. http://www.jetbrains.com Plugin homepage http://kotlinlang.org

  2. 创建一个Android Project,加一个空的MainActivity
  3. 创建一个新的Kotlin Activity(安装完Kotlin插件就自动有了), 命名为MainActivity2
  4. gradle配置 for Kotlin(据说3.0不用单独配置)

    • build.gradle(Project), 增加星号标记的两处。(版本可以从Kotlin Blog上找)

        buildscript {
            ext.kotlin_version = '1.1.4' *********
            repositories {
                jcenter()
            }
            dependencies {
                classpath 'com.android.tools.build:gradle:2.3.3'
                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
            }
        }
      
    • build.gradle(app), 增加星号标记的三处

        apply plugin: 'com.android.application'
        apply plugin: 'kotlin-android'              *********
        apply plugin: 'kotlin-android-extensions'   *********
              
        ......
              
        dependencies {
            compile fileTree(include: ['*.jar'], dir: 'libs')
            androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
                exclude group: 'com.android.support', module: 'support-annotations'
            })
            compile 'com.android.support:appcompat-v7:25.3.1'
            compile 'com.android.support.constraint:constraint-layout:1.0.0-beta4'
            testCompile 'junit:junit:4.12'
            compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"   *********
        }
      
  5. 把MainActivity删除,MainActivity2改名为MainActivity
  6. Okay了,直接运行看看
  7. 来显示个列表吧

    • MainActivity.kt

        package com.open.kotlinstart
              
        import android.content.Context
        import android.os.Bundle
        import android.support.v7.app.AppCompatActivity
        import android.view.LayoutInflater
        import android.view.View
        import android.view.ViewGroup
        import android.widget.BaseAdapter
        import android.widget.ListView
        import android.widget.TextView
        import java.util.*
              
        class MainActivity : AppCompatActivity() {
              
            internal lateinit var mList: ListView  // 对于非空类型的属性是必须初始化的,如果希望延迟进行初始化就可以用该关键字。lateinit只能在不可null的对象上使用,比须为var,不能为primitivesIntFloat之类
              
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.activity_main)
              
                mList = findViewById(R.id.mList) as ListView
                val customAdapter = CustomAdapter(this, createTestData())
                mList.adapter = customAdapter
            }
              
            internal fun createTestData(): List<String> { //在本模块之内, 凡是能够访问到这个类的地方, 同时也能访问到这个类的 internal 成员
                val data = ArrayList<String>()
                for (i in 0..49) {
                    data.add("Love World " + i)
                }
                return data
            }
              
            internal inner class CustomAdapter(context: Context, var mData: List<String>?) : BaseAdapter() {
                //加“?”和不加的根本区别在哪?就在于程序运行过程中对变量的赋值,如果给没有加“?”的变量赋值了null,程序就会异常。
                var mInflater: LayoutInflater
              
                init {
                    mInflater = LayoutInflater.from(context)
                }
              
                override fun getCount(): Int {
                    if (mData == null || mData!!.size <= 0) {//!!可以为null
                        return 0
                    }
                    return mData!!.size
                }
              
                override fun getItem(position: Int): Any? {
                    if (mData == null || mData!!.size <= 0 || position < 0 || position >= mData!!.size) {//
                        return null
                    }
                    return mData!![position]
                }
              
                override fun getItemId(position: Int): Long {
                    return position.toLong()
                }
              
                override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
                    var convertView = convertView
                    if (convertView == null) {
                        convertView = mInflater.inflate(R.layout.list_item, null)
                    }
              
                    val name = convertView!!.findViewById(R.id.tv_name) as TextView
                    name.text = getItem(position) as CharSequence?
              
                    return convertView
                }
            }
        }
      
    • activity_main.xml

        <?xml version="1.0" encoding="utf-8"?>
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context="com.open.kotlinstart.MainActivity">
              
            <ListView
                android:id="@+id/mList"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
              
              
        </LinearLayout>
      
    • list_item.xml

        <?xml version="1.0" encoding="utf-8"?>
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="15dp">
              
            <ImageView
                android:id="@+id/iv_photo"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/btn_collection"/>
              
            <TextView
                android:id="@+id/tv_name"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="10dp"
                android:layout_toRightOf="@id/iv_photo"
                android:textSize="16dp"/>
              
        </RelativeLayout>
      
  8. 效果图

Code下载

总结

总的感觉,性能上似乎没有大的改变,因为Kotlin也是基于JVM的。Kotlin有很多语法糖,不过高阶函数和方法扩展等功能有不错的体验。

不过跟RN这类跨平台相比,Kotlin的相对Java的变动是微小的。

Reference