使用Kotlin開(kāi)發(fā)Android應(yīng)用(I):簡(jiǎn)介
@author ASCE1885的 Github 簡(jiǎn)書(shū) 微博 CSDN
原文鏈接
Kotlin是一門(mén)基于JVM的編程語(yǔ)言,它正成長(zhǎng)為Android開(kāi)發(fā)中用于替代Java語(yǔ)言的繼承者卦方。Java是世界上使用最多的編程語(yǔ)言之一嗽仪,當(dāng)其他編程語(yǔ)言為更加便于開(kāi)發(fā)者使用而不斷進(jìn)化時(shí)荒勇,Java并沒(méi)有像預(yù)期那樣及時(shí)跟進(jìn)。
Java缺失的很多特性在最新的修訂版中逐漸覆蓋到了闻坚,但Android開(kāi)發(fā)者暫時(shí)還沒(méi)能夠使用它們沽翔。這就使得類(lèi)似Kotlin這樣的語(yǔ)言有了用武之地了:在舊的開(kāi)發(fā)環(huán)境中使用現(xiàn)代語(yǔ)言的特性。
Kotlin是什么窿凤?
Kotlin是由JetBrains創(chuàng)建的基于JVM的編程語(yǔ)言仅偎,IntelliJ正是JetBrains的杰作,而Android Studio是基于IntelliJ修改而來(lái)的卷玉。Kotlin是一門(mén)包含很多函數(shù)式編程思想的面向?qū)ο缶幊陶Z(yǔ)言哨颂。
Kotlin生來(lái)就是為了彌補(bǔ)Java缺失的現(xiàn)代語(yǔ)言的特性,并極大的簡(jiǎn)化了代碼相种,使得開(kāi)發(fā)者可以編寫(xiě)盡量少的樣板代碼威恼。
為什么要使用Kotlin品姓?
首先我必須聲明我使用Kotlin的時(shí)間并不長(zhǎng),我?guī)缀跏沁厡W(xué)習(xí)邊寫(xiě)這一系列博客的箫措。我沒(méi)有嘗試其他替代語(yǔ)言例如Go或者Scala腹备,因此如果你真的想要切換到另一門(mén)語(yǔ)言之前,我建議先搜索其他人是如何評(píng)價(jià)其他語(yǔ)言的斤蔓。使用Scala開(kāi)發(fā)Android的一個(gè)很棒的例子可以在47deg的Github上面找到植酥。
下面是我為什么選擇Kotlin進(jìn)行學(xué)習(xí)的理由:
- 相對(duì)而言更快的學(xué)習(xí)曲線(xiàn):例如相比Scala而言,我們將學(xué)得更快弦牡。Kotlin限制比較多友驮,但如果你之前沒(méi)有使用過(guò)現(xiàn)代編程語(yǔ)言,那么使用Kotlin入門(mén)會(huì)更容易驾锰。
- 輕量級(jí):相比其他編程語(yǔ)言卸留,Kotlin函數(shù)庫(kù)更小。由于A(yíng)ndroid存在65K方法數(shù)限制椭豫,這使得這一點(diǎn)更為重要耻瑟。雖然使用proguard或者打包成多個(gè)dex能夠解決這個(gè)問(wèn)題,但是所有這些解決方案都會(huì)增加復(fù)雜性赏酥,并增加調(diào)試的時(shí)間喳整。Kotlin函數(shù)庫(kù)方法數(shù)小于7000個(gè),相當(dāng)于support-v4的大小裸扶。
- 高度可互操作:Kotlin可以和其他Java類(lèi)庫(kù)很好的并且簡(jiǎn)單的互操作框都。Kotlin團(tuán)隊(duì)在開(kāi)發(fā)這門(mén)新語(yǔ)言時(shí)正是秉承了這個(gè)中心思想。他們希望可以使用Kotlin繼續(xù)開(kāi)發(fā)現(xiàn)有的使用Java語(yǔ)言編程的工程姓言,而不是重寫(xiě)所有代碼瞬项。因此Kotlin需要能夠極好的和Java互操作。
- 完美的集成Android Studio以及Gradle:Kotlin有一個(gè)專(zhuān)門(mén)用于A(yíng)ndroid Studio的插件何荚,以及另一個(gè)專(zhuān)門(mén)用于Gradle的插件囱淋,因此在A(yíng)ndroid工程中開(kāi)始使用Kotlin并不困難(我將在下一篇文章中進(jìn)行介紹)。
在你作任何決定之前我推薦先閱讀一篇由Jake Wharton寫(xiě)的有趣的文章:在A(yíng)ndroid開(kāi)發(fā)中使用Kotlin
Kotlin有些什么特性呢餐塘?
1. 表達(dá)式
使用Kotlin可以很容易避免樣板代碼的編寫(xiě)妥衣,因?yàn)檎Z(yǔ)言本身已經(jīng)默認(rèn)覆蓋了大多數(shù)典型的情況。
例如戒傻,在Java中如果要?jiǎng)?chuàng)建一個(gè)典型的數(shù)據(jù)模型類(lèi)税手,我們需要編寫(xiě)(或者至少生成)如下代碼:
public class Artist {
private long id;
private String name;
private String url;
private String mbid;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getMbid() {
return mbid;
}
public void setMbid(String mbid) {
this.mbid = mbid;
}
@Override public String toString() {
return "Artist{" +
"id=" + id +
", name='" + name + '\'' +
", url='" + url + '\'' +
", mbid='" + mbid + '\'' +
'}';
}
}
如果使用Kotlin編寫(xiě)呢?如下所示:
data class Artist(
var id: Long,
var name: String,
var url: String,
var mbid: String)
2. 空類(lèi)型安全
當(dāng)我們使用Java進(jìn)行開(kāi)發(fā)時(shí)需纳,大部分代碼都是防守型的芦倒。我們需要在使用之前不斷的檢測(cè)對(duì)象是否為空,如果我們不想在代碼運(yùn)行時(shí)得到非預(yù)期的NullPointerException不翩。類(lèi)似其他很多編程語(yǔ)言兵扬,Kotlin是空類(lèi)型安全的麻裳,因此我們需要使用安全調(diào)用操作符顯式指明對(duì)象是否能夠?yàn)榭铡?/p>
我們可以類(lèi)似這樣聲明:
//This won′t compile. Artist can′t be null
var notNullArtist: Artist = null
//Artist can be null
var artist: Artist? = null
// Won′t compile, artist could be null and we need to deal with that
artist.print()
// Will print only if artist != null
artist?.print()
// Smart cast. We don′t need to use safe call operator if we previously checked nullity
if (artist != null) {
artist.print()
}
// Only use it when we are sure it′s not null. Will throw an exception otherwise.
artist!!.print()
// Use Elvis operator to give an alternative in case the object is null
val name = artist?.name ?: "empty"
3. 擴(kuò)展函數(shù)
我們可以為任何類(lèi)添加新函數(shù)。相比我們工程中普遍存在的傳統(tǒng)的工具類(lèi)器钟,擴(kuò)展函數(shù)更具可讀性津坑。例如,我們可以為fragments添加一個(gè)新函數(shù)傲霸,用于顯示一個(gè)toast:
fun Fragment.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) {
Toast.makeText(getActivity(), message, duration).show()
}
然后可以這樣調(diào)用:
fragment.toast("Hello world!")
4. 函數(shù)式支持(Lambdas)
每次當(dāng)我們創(chuàng)建一個(gè)新的listener時(shí)疆瑰,都需要聲明一個(gè)onClick函數(shù)用于處理監(jiān)聽(tīng)回調(diào),我們可以直接編寫(xiě)監(jiān)聽(tīng)回調(diào)的代碼而不用聲明onClick函數(shù)嗎昙啄?答案是肯定的穆役。這(包括其他很多有趣的功能)得歸功與lambda表達(dá)式的運(yùn)用:
view.setOnClickListener({ toast("Hello world!") })
目前的限制
譯者注:本小節(jié)所列出的限制,在最新版的Kotlin中已經(jīng)都解決了跟衅,僅供讀者目睹Kotlin語(yǔ)言的完善和進(jìn)化過(guò)程孵睬。
Kotlin目前還處于開(kāi)發(fā)階段播歼,雖然已經(jīng)很穩(wěn)定而且最終release版本即將發(fā)布(這個(gè)夏天)伶跷,但在A(yíng)ndroid開(kāi)發(fā)中存在如下限制:
- 與自動(dòng)生成代碼的可互操作性:一些知名的依賴(lài)于自動(dòng)生成代碼的Android函數(shù)庫(kù),例如Dagger或者Butterknife秘狞,由于某些不兼容的命名叭莫,因此不能正常的使用。Kotlin團(tuán)隊(duì)正在解決這些問(wèn)題烁试,將來(lái)某一天將會(huì)解決(KT-6444)雇初。不管怎么說(shuō),就像我將在下一篇文章中說(shuō)明的减响,語(yǔ)言的可表達(dá)性能夠說(shuō)服我們不再需要這些函數(shù)庫(kù)靖诗。
更新:在Kotlin M12已經(jīng)帶來(lái)了對(duì)注解處理的支持。
- 沒(méi)有簡(jiǎn)單的方式聲明自定義views:Kotlin類(lèi)只能聲明一個(gè)構(gòu)造函數(shù)支示,而自定義views一般都有三個(gè)重載構(gòu)造函數(shù)刊橘。當(dāng)我們?cè)诖a中使用這些自定義views時(shí)只有一個(gè)構(gòu)造函數(shù)不存在問(wèn)題,但如果想在xml文件中使用自定義views颂鸿,只有一個(gè)構(gòu)造函數(shù)是不夠的促绵。最簡(jiǎn)單的解決方法是使用Java聲明這些自定義views類(lèi),并在Kotlin中引用它們嘴纺。Kotlin團(tuán)隊(duì)許諾將在M11發(fā)布版中解決這個(gè)問(wèn)題败晴。
更新:Kotlin M11發(fā)布了并包含了輔助構(gòu)造函數(shù)。
- Android工程中的jUnit測(cè)試:Android Studio 1.1引入的這個(gè)新特性Kotlin暫時(shí)還不支持栽渴。但純粹的Kotlin工程能夠完全支持Instrumentation測(cè)試和jUnit測(cè)試尖坤。
更新:Kotlin M12的gradle plugin現(xiàn)在支持Android Studio中的單元測(cè)試了。
總結(jié)
Kotlin是開(kāi)發(fā)Android app中使用的Java語(yǔ)言的一個(gè)有趣的替換者闲擦。下一篇文章我們將描述使用Kotlin如何新建一個(gè)新工程慢味,并講解如何充分利用Kotlin使Android開(kāi)發(fā)更容易僚祷。敬請(qǐng)關(guān)注!
歡迎關(guān)注我的微信公眾號(hào)