使用Kotlin進行Android開發
What is Kotlin
Kotlin,原意是在俄羅斯的一個小島,JetBrain在2011年推出了以這個來命名的一個運行在JVM上的語言, 看上去有點類似C#和Scala的結合,并且同為靜態類型,作為一門JVM上的語言,可以輕松兼容Java,并且整個語言設計的非常輕量。目前的版本為0.12.200
,尚未發布正式版。
Kotlin的下載和配置在其官網上有,在這里就不再贅述了,值得一提的是,作為JetBrains家出品的語言,自家的IDEA當然全力支持!
基本語法介紹
Kotlin的語法非常簡潔,熟悉Java或者Scala的人都可以快速上手:
函數聲明:
fun foo(va: Int): Int {
return 1
}
也可以單行聲明:
fun foo(va: Int): Int = 1
lambda當然也是支持的:
var c = {foo: Int -> println(foo)}
Kotlin中的函數是一等對象,自然支持高階函數:
var c = {foo: Int -> println(foo)}
fun fooTest(func: (Int)->()) = println("I'm Groot")
fooTest(c)
類與接口
類可以這樣進行聲明:
class Bar(var b: Int): Foo() {
var c = 1
init {
println("class initializer")
}
constructor(): this(1) {
println("secondary constructor")
}
}</code></pre>
Bar類在這里繼承了Foo類,Bar類有兩個構造函數,直接在Bar類頭的是primary constructor,另外一個構造函數使用constructor
關鍵字定義,注意必須要先調用primary constructor,另外,init
標明的是class initializer,每個構造函數都會首先調用class initializer里面的代碼,再調用構造函數
Inner class:
class Outer {
class Inner {
}
}
Kotlin同樣支持嵌套的內部類,不過和Java不一樣的是,Kotlin的內部類不會默認包含一個指向外部類對象的引用,也就是說,Kotlin中所有的內部類默認就是靜態的,這樣可以減少很多內存泄露的問題。另外,如果需要在內部類中引用外部類對象,可以在Inner類的聲明前加上inner
關鍵字,然后在Inner類中使用標記的this
:this@Outer
來指向外部類對象
Singleton:
object Single {
var c = 1
fun foo() = println("foo")
}</code></pre>
Kotlin中使用object
關鍵字聲明一個singleton對象,后面這里的方法就可以直接使用Single.foo()
來調用了
Interface:
interface Interface {
fun foo() {
println(1)
}
fun bar()
}
Kotlin中的interface,跟其他語言的trait
非常像,而且也可以帶有默認的實現方法,并且不允許通過屬性來維護狀態。事實上,在上個版本中,interface的原來名稱是trait
,而在M12現在這個版本中又改成了interface而已
Null safe and Smart type cast
Null safe:
在Kotlin中,嚴格區分了nullable和非nullable對象,甚至在編譯期解決了不少潛在的空指針問題:
我們先來看下普通的變量聲明
var c: String = "12123"
這里聲明了一個String對象,其值為"12123",我們可以正常的使用這個對象的成員方法:c.length()
但是,如果在初始化的時候,變量c為空的話,這樣聲明就是錯誤的,會編譯不過:
var c: String = null
正確的聲明應該是這樣:
var c: String? = null
這里在String
后面加多了一個問號,表明這里是一個Nullable的對象,說明這個變量在使用的過程中可能為空,而且,在調用這個變量的成員的時候,必須要使用這種語法:c?.length()
,在調用的時候添加了一個問號,表明,如果c
為空的時候,length()
這個方法就不會調用。coffe-script也有類似的,這種語法糖減少了很多平時用到的Null-checked,簡化了代碼,而且從編譯器開始介入null-checked,大大減少了潛在的NullPointerException
,而事實上,null的確也是一個billion dollar mistake
常年進行如此的調用語法常常會很惱人,因此在你進行顯式的Null-checked的時候,Kotlin的編譯器會認為后續的調用已經無需進行Null-checked,可以直接調用了:
if (c != null) {
c.length()
}
Smart type cast
在Kotlin中,進行強制類型轉換可以使用as
關鍵字,但有可能會拋出異常,因此,Kotlin引入了smart type cast:
if (c is String) {
c.length()
}
在上面的例子中,如果c
是一個String對象,則在if塊中,可以直接使用String的方法,編譯器會智能的幫你識別出c在if-blcok里面是一個String對象
Pattern Matching
Kotlin在一定程度上支持了一些FP的特性,包括強大的Pattern Matching,在Kotlin中可以使用when
關鍵字:
var x = 3
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
in 1..10 -> print("x is in the range")
!in 10..20 -> print("x is outside the range")
is Int -> println("is int")
else -> { // Note the block
print("x is neither 1 nor 2")
}
}
Function Extension
在Java中我們經常需要給系統的類添加一些實用的方法,但苦于不能直接擴展,于是就有了各種的xxxUtils類,導致代碼非常惡心,但是在Kotlin中,我們可以直接擴展庫里面類的方法,通過function extension:
fun String.fucker() {
println("a fucker")
}
上面給String
類添加了一個fucker方法,我們可以直接使用:
"123123".fucker()
這大大的減少了我們寫xxxUtils類的必要性
配置使用Kotlin進行Android開發
使用Kotlin開發Android app的配置非常簡單,按照官方給出的配置即可,直接在Gradle的配置文件build.gradle中添加一個依賴:
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
然后添加Kotlin插件的使用:
apply plugin: 'kotlin-android'
進行一次Gradle Sync之后,就可以直接在項目使用Kotlin編寫代碼了,另外,如果安裝了Intellij的Kotlin插件,可以選擇 Tools->Kotlin->Configure Kotlin in Project
,就可以自動進行上述的配置,一步到位
我寫了一個簡單的Demo app放到了Github上,有興趣可以看下使用Kotlin開發android app具體是怎樣的:Demo地址
對于dex方法數目的影響
dex有個65535方法數的限制,這對Android開發造成了很大的影響,在使用Kotlin進行android app開發的時候,需要將Kotlin的標準庫打包進入apk中,這意味著如果標準庫過大,對分包會造成很大的限制(因為這必須得打包在主dex中),所幸的是,Kotlin的哲學是“Java中有的,就盡量復用,不再自行創造一套”,使得整個Kotlin的標準庫非常小,我們可以簡單將Kotlin的標準庫和其他比較常用庫進行一下對比:
包名
android-support-v13.jar
android-support-v4.jar
android-support-v7-appcompat.jar
guava-18.0.jar
scala-library-2.12.0-M1.jar
kotlin-stdlib-0.12.213.jar
方法數
8219
8118
4624
14833
51248
7228
可以看出來Kotlin的標準庫相當小,只有7000多個方法,比support-v13和support-v4還小,這體現了Kotlin的設計哲學之一:"100% interoperable with Java",基本上Java已經有的,Kotlin會盡量復用。而對比來看,同樣是JVM上的語言,我們也可以選擇使用Scala來進行Android開發,但Scala標準庫有5萬多個方法,全部打包進主dex中,很容易就導致app爆主dex了。所以綜合來看,輕量形的Kotlin還是相當適合進行Android開發的。
Project Anko
Anko 是JetBrains推出的一個簡化Android開發的庫,同樣由Kotlin來編寫,主要的革命在于,聲明UI的方式,完全拋棄了xml的使用,使用Anko,聲明UI是這樣做的:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val customStyle = { v: Any ->
when (v) {
is Button -> v.textSize = 26f
is EditText -> v.textSize = 24f
}
}
verticalLayout {
padding = dip(34)
imageView(android.R.drawable.ic_menu_manage).layoutParams {
margin = dip(16)
gravity = Gravity.CENTER
}
val name = editText {
hintResource = R.string.name
}
val password = editText {
hintResource = R.string.password
inputType = TYPE_CLASS_TEXT or TYPE_TEXT_VARIATION_PASSWORD
}
button("Log in") {
onClick {
tryLogin(name.text, password.text)
}
}
}.style(customStyle)
}</code></pre>
你沒看錯,的確是在Activity類的onCreate方法中直接聲明UI的布局。
Anko看起來像是使用了一種類似DSL的方式聲明了界面的UI,這里主要是使用了Kotlin的其中兩個特性:
- Function Extension,Anko擴展了Activity類,提供了額外的方法和屬性
- Kotlin在調用函數的時候,如果最后一個參數為函數的話,則可以直接使用Lambda,并省略括號
因此這里聲明布局的方式,其實全是Kotlin的原生代碼,鵝妹子嚶!這樣做有顯然的好處:
- 由于實際上全是由代碼來布局,省去了解析xml的時間
- xml本身有許多缺點,例如不可重用,非類型安全等,使用代碼布局的話,我們可以很容易的就解決這個問題了
來自:http://blog.csdn.net/chaoyu168/article/details/52047687