Kotlin 语言高级安卓开发入门

过去一年,使用 Kotlin 来为安卓开发的人愈来愈多。即便那些如今尚未使用这个语言的开发者,也会对这个语言的精髓产生共鸣,它给如今 Java 开发增长了简单而且强大的范式。Jake Wharton 在他的 Øredev 的讨论中,提到了 Kotlin 是如何经过提高安卓开发的语言特性和设计模式来解决这些严重的问题,经过这些方法你能够清除那些无用的 API 还有无效代码。充分利用扩展特性来解决你的开发中的模板性代码的问题!java

 
为何要推广这个语言?
 
好吧,大伙。欢迎来到这里。咱们今天的主题是使用 Kotlin 语言的高级安卓开发 – 推广咱们开发应用的语言。首先呢,咱们须要弄清楚咱们为何要在安卓开发中更进一步?为何咱们须要一些新的东西来推动安卓开发?
 
许多人都会提到的一个经典的缘由就是咱们如今被 Java 6-ish 困住了,Java 7 也差很少是一样的情况。这被称做是一片荒地。
 
javax.time 是 Java 8 才引进的新库, JSR310。这个库咱们在安卓上没有,因此咱们被老的日期和日历的 API 困住了,它们都很是容易出错。
 
Java 8 的另一个功能 streams,安卓也没有。咱们还缺乏其余的语言特性,好比 lambdas,method references 和 不引用 outer class 的 anonymous classes。最后,咱们没有 try-with-resources。Try-with-resources 不在 Java 7 里面,而安卓在 API 19 中大部分都是 Java 7, 在 API 20 中又增长了点,但不是所有。因此只有当你的定义最小的 SDK 的时候,你才能用这些相关的功能。
 
Java 6 不是个问题 
 
尽管上面4个问题都看起来十分使人头疼,可是事实上它们不是。关于 javax.time,为 Java 8 SDK 编写的大部分代码大部分都可以以 ThreeTenBP 的形式向后兼容 Java 6,因此你能够这样使用。
 
关于 streams,Java 6 上也有一个向后兼容的移植或者一个经常使用的 Java 库,RxJava 实现了一样的概念,只不过用了一种略微不一样的有争议性的更强大的方式。
 
也有一个工具叫作 Retrolambda,它事实上也能够运行 Java 8 bytecode 而且向后兼容了 lambdas 和 method references 到 Java 6。
 
最后,如我所说,若是你的最小的 SDK 是 19 的话,你可使用 try-with-resources,并且 Retrolambda 也会容许你这样作。
 
这些关于 Java 6 是个问题的争论都有工具去解决它们。固然,若是咱们能使用 Java 8 是最好的,可是这些替代方案都是通过实战测试并且可以很好地工做的方案。因此上面的理由就不太算数了。不管如何,有两个方面我想重点讨论一下,由于这两个方面没有相似的解决方案。
 
Java 语言的限制和问题
 
Java 语言的一些限制和所带来的一些问题,这些问题 Java 语言自己是不可避免的。例如,咱们不能给不是咱们本身写的 types、classes 或者 interfaces 增长新的方法。长时间以来,咱们都会采用 util 类,杂乱无章地堆砌着咱们代码或者或者揉在同一个 util package 里面。若是这是解决方案的话,它确定不理想。
 
Java 语言的类型系统都有 null 的问题,在 android 上更为明显。由于它没有对多是或不是 null 的类型完成 first-class representation。因此,被称做 “billion dollar mistake” 的 null 指针异常最后会毁了你的应用。
 
接下来, Java 确定不是最简洁的语言。这件事自己不是件坏事,可是事实上存在太多的常见的冗余。这会带来潜在的错误和缺陷。在这以前,咱们还要处理安卓 API 带来的问题。
 
Android API 的设计问题
 
安卓是一个庞大的继承系统;他们为他们的继承系统而感到自豪,对他们来讲这个系统工做的也很是的正常,可是这个系统倾向于把问题推向应用开发者。并且,空引用的问题也回来了,这个问题在安卓系统中十分明显,由于他们想让系统更加有效些。null 被用在许多地方来表明值的缺失,而不是封装成更高级的类型,好比一个类型或者可选项。
 
同时,回到语言的冗余,安卓的 API 有着本身许多的范式。这也许是由于性能的缘由。设计者们最后写出的这些 APIs 须要你,开发者,来作许多的事情来提升效率而不是用其余的方法抽象它们。
 
因此说 Java 语言和安卓 API 是驱动咱们转向相似 Kotlin 语言的两个重要的因素。这不是说 Java 6 没有问题,由于 Kotlin 解决了 Java 6 的许多问题,可是我不认为那是 Kotlin 做为一个替代方案的充分缘由,由于其余的方案也能够带来一样的好处。
 
Kotlin 入门 
 
Kotlin 是公司 JetBrains 研发的语言。市面上为各类语言开发的 IDE 不少,可是 Intelli J 平台是 Android Studio 的基础。在他们的网站上,他们这样描述 Kotlin :
 
为 JVM、Android 和浏览器而生的静态编程语言。
它的目标是 JVM、安卓和 Java 6 字节流。他们想在他们的语言里增长这些特性,并且持续支持 Java 六、JVM 和安卓系统市场。他们特别关注和 Java 的相互调用,这点接下来会讨论。
 
Kotlin 语法速成
 
网站上有许多的很棒的指导来学习语法,可是我仍是会很快地介绍一下,而后再解释为何这些语法有利于安卓开发。咱们以一个这样的方法定义的语法开始。
 

[代码]csharp代码:

?
1
2
3
fun sum(a: Int, b: Int): Int {
   return a + b
}
咱们有一个 “fun” 的定义,这表明着函数。函数名和第一个要注意的事情是这和 Java 有明显的不一样。参数名的顺序和参数的类型保留了下来 – 名字后面跟着类型。返回值类型在函数末尾声明。没有分号。
 
另一个有意思的事情是这个函数还能够有单行描述,咱们事实上能够不用大括号和 return,定义函数和表达式同样。
 

[代码]csharp代码:

?
1
fun sum(a: Int, b: Int) = a + b
咱们接下来还会看到更简洁的语法。这里有另一个例子,这个看起来像一个 main 函数,若是你写一个普通的 Java 应用的话:

[代码]csharp代码:

?
1
2
3
fun main(args: Array< string >) {
   println( "Args: $args" )
}</ string >
数组的语法不太同样。可是处理得十分天然。 编译后的字节码会使用一个字符串的数组,可是在你的代码里却把它处理地像一个普通的数组。它也支持字符串的插入;咱们能够写一个串,而后引用它其中的变量,而且能够自动的替换其中的变量。
 
最后,看看变量:

[代码]csharp代码:

?
1
2
val name = "Jake"
val people: List< string > = ArrayList()</ string >
这里我用一个叫作 “name” 的变量给一个字符串命名,并且这里没有类型定义。语言会自动解释类型,由于它只多是串。它有 “val” 的前缀而 “Val” 是它的值,而且是个不能够修改的值。若是咱们想修改它,咱们就须要用 “var” 做为前缀定义变量。
 
这个 : List<String> 是一个看起来像在 field 上的类型,它接在名字后面,像一个方法。最后,当咱们调用构造函数的时候,咱们不须要使用 “new” 关键字。其余的语法都是同样的,就是不要 “new”。
 
Kotlin 语言特性 
 
让咱们看看那些语言自己的特性,看看他们是如何帮助咱们构建安卓应用的。我指出过这些 util 类都是反设计模式的,并且它们会在你的应用里愈来愈不受控制……
 
函数扩展 
 
Kotlin 有扩展函数的概念。这不是 Kotlin 语言独有的,可是和其余语言里面咱们看到的扩展又不太同样。若是咱们在纯 Java 语言的环境下添加一个 date 的方法,咱们须要写一个 utils 类或者 dates 类,而后增长一个静态方法。它接收一个实例,而后作些事情,可能会返回一个值。
 

[代码]java代码:

?
1
2
3
4
5
static boolean isTuesday(Date date) {
   return date.getDay() == 2 ;
}
 
boolean tuesday = DateUtils.isTuesday(date);
这里我增长一个十分有用的 “isTuesday” 函数给咱们的 date utils,而后咱们用传统的静态方法调用它。在我展示 Kotlin 语法前,我想和 C# 作个比较。这是在 C# 中咱们须要在 date 类中添加一个函数的实现, DateTime:

[代码]java代码:

?
1
2
3
4
static boolean IsTuesday( this DateTime date)
{
   return date.DayOfWeek == DayOfWeek.Tuesday;
}
这里咱们获得 date 的实例,而后调用这个方法,在任何 .NET 环境下这都能行得通,只要你在某处定义了该扩展方法,你能在你的整个项目中都能引用到 DateTime。我接下来会解释一个有意思的语言特征。这是 Kotlin 定义的方法:

[代码]csharp代码:

?
1
2
3
4
5
fun Date.isTuesday(): Boolean {
   return getDay() == 2
}
 
val tuesday = date.isTuesday();
在 Kotlin 中,咱们用咱们想增长的函数的方法的类型来给原有的函数名增长了一个前缀。咱们如今调用 Date.IsTuesday 而不是 isTuesday。而后你能在最后获得返回值。咱们最后能调用 “getDay” 而且这个扩展的方法可以被调到,尽管咱们没有使用实例来调用它。咱们的调用方式和该类原来就有有这个方法时调用的方式同样。咱们也可以在 Date 上调用其余的方法。
 
Kotlin 的一个很是好的功能是,它会自动地转换有 getters 和 setters 综合属性的类型。因此我可以替换 getDay() 为 day,由于这个 day 的属性是存在的。它看起来像一个 field,可是其实是个 property – getter 和 setter 的概念融合在了一块儿。
 
前面我指出的单行函数表达式会使得语法变得更简洁,因此咱们能够把上面的代码修改为下面的样子,而且隐藏返回值:

[代码]csharp代码:

?
1
fun Date.isTuesday() = day == 2
如今咱们有一个很是漂亮的单行实现的而且在 date 上使用的扩展方法了。
 
不像 C#,若是咱们不在同一个 package 里面的话,扩展函数须要显示引用。若是不是同一个文件里,咱们须要很是清楚地描述这个函数从何而来: import com.example.utils.isTuesday
 
这和 Java 的静态方法 import 很是相似。咱们须要显示声明咱们调用的函数,这样函数的来源就不会模糊。由于当我看到这段代码时,做为一个 Java 开发者,我知道 date 没有 “isTuesday” 的函数,可是显式的 import 告诉我它来自于公共的某个 util package。而在 C# 中,咱们不知道这个扩展函数从何而来。它可能来自一个库,你的源代码,或者其余的地方,你没法静态地知道,除非你到 IDE 里面找到它的定义。
 
固然,你能够 command B 而后进入这个函数,这看起来像是 date 类型的一个方法。这和咱们在 Java 里面编写它,而后产生的二进制代码如出一辙。并且,由于它关注 inter-op,你能够从 Java 侧使用一个自动生成类来调用它。
 
类型系统中的 Null 
 
我提过 null 会是个问题。Kotlin 事实上在它的类型系统里从新表述了 null。对于 get string 可能返回 null 的函数来讲,我会返回 String? 来表述这多是个 null 值。而后在 get string 函数中,我使用 double exclamation mark 语法来直接调用这个 null。这基本上是说,“我知道这多是个 null,因此把它变成一个普通字符串。” 当它真是 null 的时候,它会发出一个检查的信号,而后抛出异常。
 
可是在消费者的代码里面,代码每每是直接调用该函数,类型系统会生成一个带有问号的字符串,而且传递到调用者的代码处。这意味着若是你不首先作 null 检查或者提早的默认处理机制,你就永远不能解引用。这样,它会最终解决消费者代码中致使 null 指针异常的问题。
 
函数表达式入门 
 
另外,函数表达式也被称做 lambdas 或者 closures。这里有一个最简单的函数表达式: { it.toString() }。它是一段代码在 “it” 变量上调用了 two-string 函数。“it” 是个 built-in 的名字。当你在写这些函数表达式的时候,若是你只有一个参数传入这段代码,你能够用 “it” 引用,这只是一个你不须要定义参数的方法。
 
可是当你须要定义参数的时候,或者不止一个参数要定义的时候,语法就是这样的: { x, y -> x + y }。咱们能够建立一段代码,一个函数表达式,输入两个参数,而后把它们相加。若是咱们愿意,咱们能够显示定义类型。
 

[代码]csharp代码:

?
1
2
3
4
5
{ x, y -> x + y }
 
val sum: (Int, Int) -> Int = { x, y -> x + y }
 
val sum = { x: Int, y: Int -> x + y }
而后,在 fields 上存储它们。如今你能够看到在前二个例子中,类型是在 field 本上上定义的。这意味着函数表达式不须要任何类型信息。而后往下一个,类型信息在函数表达式里面本身包含了,因此咱们不须要在变量定义时加入类型信息。
 
在最后一个例子中,返回值是推断出来的。两个整型相加,输出只能是整型。因此你不须要显示定义它们。
 
Higher-order 函数 
 
这是个新奇的术语,它指的是函数能够接收函数,或者函数能够返回函数。这里是个例子

[代码]csharp代码:

?
1
2
3
4
5
6
func apply(one: Int, two: Int, func: (Int, Int) -> Int): Int {
   return func(one, two)
}
 
val sum = apply(1, 2, { x, y -> x + y })
val difference = apply(1, 2, { x, y -> x - y })
这里咱们定义一个函数,接收两个整型做为参数。而后第三个参数是一个函数。这和咱们以前看到的语法同样,那里咱们定义了一个函数接收两个整型并返回一个整型。
 
而后,在函数体内部,咱们调用了该函数,而且传入了两个参数。这就是咱们如何使用它来计算和或者其余的东西的方法。咱们把这段代码应用到了这两个数字上。回到以前所说的地方,咱们说这段代码知道如何相加或者相减,并且咱们把它运用到咱们传入这个方法的数据上。而后这段代码在本身合适的上下文环境中自动运行。
 
Kotlin 给你提供了一个手动的方式来调整这段代码成为更好的语法表达。若是函数的最后一个参数是个表达式,你一直都不须要使用括号,你能够只用在全部参数初始化后添加一个。

[代码]csharp代码:

?
1
2
val sum = apply(1, 2) { x, y -> x + y }
val difference = apply(1, 2) { x, y -> x - y }
这项技术容许你建立很是漂亮的 DSL 和 API。你能够像 Int 的扩展同样来编写它们。
 
包含 higher-order 函数的应用 
 

[代码]csharp代码:

?
01
02
03
04
05
06
07
08
09
10
11
12
fun <t> List<t>.filter(predicate: (T) -> Boolean): List<t> {
   val newList = ArrayList<t>()
   for (item in this ) {
     if (predicate(item)) {
       newList.add(item)
     }
   }
   return newList
}
 
val names = listOf( "Jake" , "Jesse" , "Matt" , "Alec" )
val jakes = names.filter { it == "Jake" }</t></t></t></t>
一个常见的操做是你有一个事情的列表,而后你须要基于一些条件来过滤它们。由于咱们有 extension methods 和 higher-order functions,咱们能够在列表上写一个这样的函数。这和你指望的实现同样,这个函数比较每一个列表中的元素而后返回正确的结果。
 
如今若是你有一个包含数据的列表,只需用一行代码,如此简洁的函数就能过滤出咱们想要的数据。谢天谢地,这个功能实际上已经在 Kotlin 标准库里面包含了,这样咱们就不用扩展列表类了。
 
大部分 Kotlin 的库都已经实现了现有的 Java 类型中相似的高级函数来,这样能够统一在这些类型上的操做。
 
看看这个在 Kotlin 标准库里面不存在的应用:

[代码]csharp代码:

?
1
2
3
4
5
fun Any. lock (func: () -> Unit) {
   synchronized ( this ) {
     func()
   }
}
除了同步阻塞代码块,咱们能够用一个表达式来实现同步阻塞。 “Any” 是 Kotlin 的对象版本。全部的类型都是 “Any” 的子类型。咱们能够对它增长一个方法,该方法输入是一个函数,而后执行这个函数的代码,这段代码会同步该实例。若是咱们须要一样的锁,或者一些对象须要被锁住,咱们能够把这段代码放在函数内部的锁起来。而后咱们把它传给每一个实例的这个方法中。这个方法简化了调用者的代码,并且清晰不少。
 
简单清晰的锁
 
另外一个十分酷的应用存在于咱们经常使用的锁的情景中,咱们经常忘记在一些操做以前完成锁的操做。咱们能够写这样的类,这个类只容许你访问你须要用锁才能操做的资源。

[代码]csharp代码:

?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
data class Lock<t>( private val obj: T) {
   public fun acquire(func: (T) -> Unit) {
     synchronized (obj) {
       func(obj)
     }
   }
}
 
val readerLock = Lock(JsonReader(stream))
 
// Later
readerLock.acquire {
   println(it.readString())
}</t>
在这个例子里面,咱们建立了依赖流的 JsonReader。设想不论什么缘由咱们须要多线程同时访问它,这样咱们就必须使用锁,锁会帮助咱们管理同步的问题。
 
而后在后面的代码中,咱们调用了这个 acquire 的方法,它会在这个 JsonReader 的实例上实现同步,而后把它传给咱们提供的函数。因此在这种状况下,咱们会在这个 JsonReader 里面再次析构,因而咱们须要使用锁。但如今咱们的代码根本没有处理锁的问题。咱们也没有显式的同步,也没有为 JsonReader 建立锁。但是访问 JsonReader 不使用锁是不可能的。
 
避免 Kotlin 带来的泄露
 
前面,我提到过关于 data 的代码,定义了一个这样的值:
 

[代码]csharp代码:

?
1
val notEmpty: (String) -> Boolean { !it.isEmpty() }
Kotlin 实现函数表达式的方法和在 Java 里面使用类的方法是同样的。好处是 Kotlin 并无建立对于外部范围的引用,由于没有这样的类。这样避免了可能的上下文泄漏。
 
咱们须要关心的就是传入的数据。它会致使建立一个静态的单例实例并且没有引用。用这些函数表达式根本不可能产生上下文泄漏。可是在最上层,咱们两个是如出一辙的。
 
扩展函数表达式的例子
 
扩展函数 – 给一个类型加入函数可是不修改原来的类型。
 
函数表达式 – 未定义的函数体被用做表达式(i.e.,date)
 
Higher-Order 函数 – 一个参数是函数或者返回是函数的函数。
 
扩展函数表达式是上述三个概念的综合体,这是个强大的并且能够建立清晰的 API 的方法。为了说明这点,我将使用一个 databases 的 API 作为例子,把它改形成一个更加整洁的、没有无效代码的 API。
 

[代码]csharp代码:

?
1
2
3
4
5
6
7
db.beginTransaction();
try {
   db.delete( "users" , "first_name = ?" , new String[] { "Jake" });
   db.setTransactionSuccessful();
} finally {
   db.endTransaction();
}
若是你想在一个 transaction 里面执行一个 statement 的话,这是你必须写的六行代码。咱们开始一个 transaction,咱们把它放在 “try finally” 里面,而后咱们标记这个 transaction 为成功。若是它抛出或者不在 “finally” 里面抛出异常,咱们须要结束 transaction.
这是一个容易带来 bug 的代码,容易健忘的代码和应该重构的代码。任何事情都有可能出现错误,在这里你不当心交换了两个事情,而后忽然,你就会有一个很难找到缘由的 bug。 或者它会在运行时 crash。
扩展函数表达式容许咱们解决这个问题。咱们如今能给 database 本身增长一个方法, 这将给现有的代码构建一个防御墙。
 

[代码]csharp代码:

?
01
02
03
04
05
06
07
08
09
10
11
12
13
fun SQLiteDatabase.inTransaction(func: (SQLiteDatabase) -> Unit) {
   beginTransaction()
   try {
     func( this )
     setTransactionSuccessful()
   } finally {
     endTransaction()
   }
}
 
db.inTransaction {
   it.db.delete( "users" , "first_name = ?" , arrayOf( "Jake" ))
}
开始一个 transaction,调用 “try” 代码段,而后设置 transaction 为成功,最后,结束它。咱们接收一个函数做为参数,在使用这个小技巧后,咱们在 “try” 代码段里面执行该函数。在咱们的消费者代码里,咱们会调用这个咱们称做 inTransaction 的方法,在这个方法里面咱们写的代码都会在一个 transaction 里面执行。你没有别的办法来错误地使用它了。
 
渠道化你的内部 SQLiteDatabase 
 
一个有趣的事情是,在这样的实现方法下,你的代码里面仍是会须要 database 的引用。这也是可能会出错的地方。若是你有两个数据库,你可能会在 transaction 里面引用了那个错误的数据库。
 
咱们有多种方法来解决这个问题。一个方法就是咱们可让函数的参数包含须要发生 transaction 的数据库的引用。咱们传了 this 给函数,而后咱们就不须要调用 “db”,而是使用 “it” 了,它是传给表达式的第一个参数。
 
这个方法仍是不太好。咱们阻止了潜在问题的发生,可是如今咱们每次访问 database 的时候都须要调用 “it”。这里有个有意思的事情是输入参数是个函数。咱们能够把这个函数改写成 “SQLiteDatabase” 的一个扩展函数。
 
这将会使你有些迷惑,由于它是个疯狂的强大的概念。经过把 func(this) 替换成 this.func(),传入的函数参数变成了该对象的扩展函数,并且这个扩展函数已经存在 “SQLiteDatabase” 里了。由于咱们并非真正须要 this,因此咱们抛弃了它。
 
这个函数会像在 SQLiteDatabase 里面定义的那样执行。若是咱们调用删除方法,咱们不须要用任何东西来证实本身有资格调用,由于咱们就是个 SQLiteDatabase。如今咱们能够不须要 it 了,因此每个你放在这个代码段里面的表达式都会看起来像 SQLiteDatabase 内部的一个私有方法同样。你不须要证实本身是正确的,由于它老是能在正确的对象上执行本身。
 
这太棒了,它会把你的代码改编成:

[代码]csharp代码:

?
1
2
3
4
db.inTransaction {
   it.db.delete( "users" , "first_name = ?" , arrayOf( "Jake" ))
}<font face= "Tahoma, Arial, Helvetica, snas-serif" ><span style= "font-size: 14px; white-space: normal;" >
</span></font>
避免额外的垃圾回收
 
这仍然是安卓的一个大问题。等效的 Java 代码中,咱们建立了一个函数的新的实例,而后把它传给了咱们产生的静态方法。这很是不幸,由于在咱们顺序执行代码以前,咱们并无真正地分配内存。
 
若是咱们用 Java 来实现这个,咱们须要在每次使用这些函数表达式的时候都分配一些极小的函数对象。这很差,由于这会触发许多的垃圾回收。
 
谢天谢地,咱们有办法在 Kotlin 里面来避免这个问题。咱们这里的函数仅仅是个定义好的函数表达式。它使用函数表达式做为入参,这会是个问题。那个函数表达式须要转成一个匿名类。

[代码]csharp代码:

?
1
inline fun SQLiteDatabase.inTransaction(func: SQLiteDatabase.() -> Unit) { ... }
咱们能够把它变成一个 in-line 的函数,这样咱们就告诉了 Kotlin 编译器不要把它做为一个静态函数调用,我须要编译器仅仅把个人函数代码替换到须要调用的地方。虽然这样会产生不少的 bytecode,可是这样产生的 Java 类文件会和容易出错的 Java 代码编译出来的类文件同样的。
 
经验法则:函数表达式加上 in-line 函数和一样实现的 Java 代码如出一辙。如今咱们就能清理咱们想清理的任何 API 了,找到你安卓里面最差的 API,这样的 API 确定处处都是。这其中有不少是基于 transaction 的,因此咱们能够为 fragments 或者为 shared preferences 使用一样的模式。这是一个增长功能的好方法,并且不会对自动产生的代码带来额外开销。
 
JetBrains 提供的 Anko 
 
JetBrains 的同事把这个思路用到了极致,而且建立了一个库叫作 Anko。基本想法是 XML 描述性很是好,并且很适合定义 UI,由于它是分级的。当你建立 UI 的时候,它们也是具有分层特性的。
 
在这些函数表达式的帮助下,咱们能够用一样分层式方式来编写代码。固然咱们还可以引用其余全部的方法,其余的重构工具,和其余的 Java 代码的静态分析工具来展现 UI。
 

[代码]csharp代码:

?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
verticalLayout {
   padding = dip(30)
   editText {
     hint = "Name"
     textSize = 24f
   }
   editText {
     hint = "Password"
     textSize = 24f
   }
   button( "Login" ) {
     textSize = 26f
   }
}
这仅仅是扩展函数表达式的一个发展分支。它们会建立这些类的实例,把它们加到它们的父亲那里,设置合适的属性。除了咱们在 XML 里面使用的概念之外,好比 layout,你能够调用一个函数来返回这些 layout 和把这些东西组织在一块儿。
 
这必定是个有趣的概念。但不必定适合每个人。它们也有定制的预览插件。使用 XML 的一个好处就是你能够预渲染视图,而后看到它在设备上的样子。他们也写了一个为 Java 代码的工具,这个工具能够解析 Kotlin 代码而且完成渲染。
 
这也是个 XML 也会使人烦恼的例子。Java 和 XML 这两个分离的系统,会带来一些通常的麻烦。而这个方法会把这两个分离的系通通一到一个 Koltin 的源文件里面。这会致使性能的提高,由于你减小了 XML 解析的开销,也会减小寻找 XML 中定义的类而发生的反射的开销。
 
因此虽然不是每一个人都喜欢这个解决方法,可是这确是个解决他们碰到问题的新的方案。
 
结论 
 
我想给大家介绍如今解决安卓系统中的问题过程当中的最有用的一些概念。Koltin 语言还有许多其余的通常性的改进,但那都是为了 Java 语言的。
 
这就是今天我想讨论的让你意识到的一些安卓系统开发的问题和可能解决它们的具体途径。Kotlin 网站 有着很是多的好的资源。那有一个交互性编辑器,使用它你能够在你的浏览器里面建立和运行 Kotlin 代码。
 
在一样的编辑器里面,它们也有一系列的交互性教程来帮助你一步步学习语法。
 
语言还处在 1.0 beta 的状态,因此对于那些由于这个缘由而持观望态度的人,大家很快就能加入了。我鼓励大家都试试 Kotlin 语言。
相关文章
相关标签/搜索