程序员人生 网站导航

Android@Kotlin 在Android studio 中配置Kotlin

栏目:互联网时间:2016-06-23 08:53:14

在Android项目中配置Kotlin

官方文档讲了如何1步步安装Kotlin插件,并使用插件在Android项目中自动修改Gradle文件来添加对Kotlin的支持。我不建议大家这么做,由于这样自动完成的结果可能其实不完善,即便修改后的Gradle文件工作正常,也会打乱Android项目中Gradle文件的1般情势。

说实话,我1直不喜欢有些Android Studio插件直接修改Android build文件,由于常常弄得很乱,我又得1点1点清算直到符合我的风格。Gradle构建文件也是源代码,而这些插件其实不善于修改已存在的代码。所以如果你也和我1样有些挑剔,那就多花1分钟和我1起手动配置。

下面我们要分4步完成Kotlin的配置。

  1. 新建1个Android项目。

  2. 修改Gradle代码来添加Kotlin Gradle插件与标准库。

  3. 在IntelliJ或Android Studio中添加Kotlin插件。

  4. 将Java类文件转换成Kotlin。

首先,直接以默许方式新建1个Android项目,此时应当自带1个Activity。以后,要在两个build.gradle文件中添加5行重要代码,我都在其后添加了注释。下面让我们先修改最高层的build.gradle脚本,添加两行代码。

这样就会在项目构建时添加Kotlin Gradle插件。请注意上面在ext.kotlin_version中标注的kotlin版本字符串,我们1会还要在app模块的compile dependencies中用到它,而且两个地方版本必须符合。你最好使用官方文档中最新版本。

然后,在app模块自己的build.gradle文件中紧随Android plugin添加kotlin-android plugin。这样全部项目就整合了Kotlin,在build项目时会编译Kotlin文件,这样最后所有的类文件都会打包在1个app中。

惯例上,Kotlin文件寄存在src/main/kotlin路径中,但也能够把他们和Java文件1起放在/src/main/java路径中。这里我们还是依照惯例,并在Gradle中标注1个新的Kotlin源路径。

不要忘了新建这个路径,1会就要用到了。最后需要添加1个Kotlin依赖,直接使用build.gradle中的kotlin版本变量。

不过这个包有多大呢?好问题!每当我们添加新的依赖时,都应当弄清楚这个包有多大。不过对这个问题,我会在后面的文章中回答。

这就是Kotlin Gradle插件,走完这些步骤后,就能够在项目中运行Kotlin代码了。不过你还需要添加IDE对Kotlin的支持,所以如果你还没有安装IntelliJ或Android Studio的Kotlin插件,那就赶快安装。安装Kotlin插件就像安装其他任何插件1样,可以在Preferences->Plugins->Insall JetBrains plugin下找到。安装后要重启IDE,做完这1步后,准备工作就完成了。我发现IDE对Kotlin的支持乃至和Java语言1样好。这也能够理解,毕竟IDE和Kotlin都是JetBrains开发的嘛。

快速将Java转成Kotlin

IDE插件有1个很有趣的功能就是将Java文件直接转成Kotlin。这个插件可以很智能地将Java语言风格转换成Kotin风格并保持运行兼容。如果你创建了1个Android项目,那就找到自动生成的MainActivity,在左侧的项目结构当选中,并触发IDE的action "Convert Java File to Kotlin File"。你可以按下快捷键Command+Shift+A(OSX)来选择action。这个插件乃至有专门针对这个action的快捷键Option+Shift+Command+K(OSX)。其实官方其实不建议直接转换Java文件,但直到现在我还没遇到过甚么问题。

如果你按我说的操作转换了Java文件,就会在本来.java文件的地方找到1个.kt文件。

你可以看到现在MainActivity在右下角有1个K标志(这里隐藏了.kt扩大名)。由于我们刚刚专门为Kotlin配置了1个路径,我们把Kotlin文件拖进kotlin文件夹中。注意要保存kotlin文件中类的包名,不然项目没法运行。

如果你想在项目中只用Kotlin,那可以干脆删除掉Java文件夹,把所有的Kotlin文件放在kotlin路径中。以后,项目结构就像下面这样。

重新的Activity中你可以大概知道Kotlin长甚么样。我下面说几点Kotlin与Java很不1样的地方:

  • 在Kotlin中你见不到"new"关键字。

  • 把类名当作方法并传入参数就能够直接构造对象。

  • 数据类型关键字被val(final)与var(variable)取代,Kotlin可以自己判断数据是甚么类型。

中场休息

刚才我们1步1步在Android项目中添加了Kotlin支持,现在我们要开始通过代码直观感受Kotlin的语言特点和它能如何简化Android开发。

当我第1次接触Kotlin并了解其语言特点功能时,有1点让我感触很深,那就是type-safe builders。它让你以陈说式语言风格来创建对象,其语法很类似Gradle,但Gradle和Groovy代码是动态编写的,而kotlin是静态编写的,所以编译器可以在属性的值不合法时告知你。

type-safe builders的1个典型用法就是构建嵌套式数据结构,比如XML。在Android中有很多XML文件,如layouts和views。如果Kotlin可以以程序的方式动态编写XML,它可能很善于处理层级问题。所以我决定尝试使用Kotlin创建1个动态构建View层级的工具。如果是在Java中做这件事,代码量之大可以想象。

注意:在后面的代码中我会常常使用lambda,所以在继续浏览之前,确保你了解lambda的基本情势。简而言之,lambda是要作为参数被传入某方法或赋值给某变量的匿名方法的简化表现情势。

type-safe builders可行还要归功于Kotlin的1个特点功能:lambda with receiver。下面我们要看1个能真正有用的案例。kotlin可以在类的外面定义方法,我在这里就是这么干的。还要注意变量的名字是在类型之前的,这1点与Java语言正相反。

(点击放大图象)

简便起见,我将上面的方法命名为v,在以后的系列文章中我还会使用到这个方法。这个方法是这么调用的:

这段代码和填充下面这段XML是等效的。

OK,如果这是你第1次看Kotlin代码,相信有很多需要翻译的。下面解释1下刚才代码中触及的几个语法。

<reified TV : View>

reify的意思是具体化。而作为Kotlin的1个方法泛型关键字,它代表你可以在方法体内访问泛型指定的JVM类对象。这段代码的意思就是v方法要使用命名为TV(意为Type of View,即View种类)的reified泛型,它指定类必须为View或其子类。必须之内联方式声明这个方法才有效。调用者要给TV指定1个具体的类型。

init: TV.() -> Unit

v方法有两个参数,1个是Context,1个是lambda风格的init。init在这里很特殊,由于它是1种lambda with receiver类型的方法援用。lambda with receiver是1个要求特定类型的对象的代码块,这里要求的对象在lambda代码中通过this关键字援用。在这里receiver对象就是reified泛型TV。

在我们这个例子中,v要创建1个类型为TV的对象,需要调用者告知它如何创建。这个新创建的TV类型对象会成为给定的lambda的receiver,labmda通过view.init()在v中被调用,以便对view进行操作。“-> Unit”意思是lambda返回Unit类型,就如Java中的Void1样,即甚么也不返回。

总结1下这里的lambda with receiver:

  • v声明了1个名叫init的参数,它是TV类型的lambda with receiver。

  • v创建并初始化1个TV对象,并在其上调用lambda来初始化它。

  • lambda在自己代码块中通过this关键字援用TV对象。

TV::class.java

通过TV::class.java表达你可以援用reified泛型TV的Class对象。这类表达在Kotlin中专门针对reified泛型,与Java相比,可以大量减少代码。

到这里,估计你会有1些问题:

为何v有两个参数,而调用的时候似乎只给了1个?

这个只是由于Java程序员对Kotlin语法其实不熟习。在Java中,1个方法的所有的参数都要写在圆括号内,所以当有匿名回调方法时会变得很长。但在Kotlin中,当lambda时最后1个参数时,有1个特殊语法,即lambda出现在紧随圆括号的大括号中。你可以把所有的代码都放在圆括号内,但大多数情况下这么写代码会显得更加简洁,而且可使1组圆括号保持在1行里,更容易于追踪。另外,这类语法在传入只有1个方法的匿名内部类比如Runnable时也能够派上用处。

layoutParams和text是变量吗?

lambda with receiver的1个语法特点就是当操作this的方法或属性时this关键字可以省略。但在上面的调用例子中layoutParams和text究竟是甚么?其实这些属性是Kotlin提供的receiver类型(TV)的属性。由于TextView有setLayoutParams()与setText()等方法,Kotlin会自动辨认这些JavaBean风格的方法并为他们创建属性,好像它们是类的成员变量1样。所以这里text = "Hello"等价于this.setText("Hello")。下面是在安装了Kotlin插件的Android Studio中的截图,里面展现了自动完成的内容。

如你所见,Kotlin插件的地方text属性是从TextView(receiver对象)中JavaBean风格的getter/setter方法中派生出的。

构造器究竟是怎样运作的?就不能new TV(context)吗?

由于编译器也不知道在v方法内部TV究竟是甚么类型,我们不能new它的对象。不过我们可以利用reified Class对象(TV::class.java)来获得唯一1个context参数的构造器。View都有这样1个构造器,不然我们也写不出这个程序。我们通过构造器对象来取得TV类型的实例,就如Java中的new关键字1样。想想我们可以通过1个方法适配所有View,而不再针对每一个View单独写方法,这1点小麻烦还是很值的。在后续系列文章中我们也会优化这个方法。

这几行代码真的很大的简化了我们的工作。如果你刚刚接触Kotlin,建议你从头再消化1遍,毕竟许多概念和Java差别很大。我自己也花了好多时间来理解这些概念。

这些都只是开始,这个方法有很多地方可以完善和升级,使之更加易用。比如我想用用1行代码构造1全部View层级。所以不要走开,我会在后续文章探索Kotlin还能做甚么。



------分隔线----------------------------
------分隔线----------------------------

最新技术推荐