通過Kotlin構建android工程

zyl409214686發表於2017-12-23

####介紹 Kotlin是JetBrains創造的一種程式語言,IntelliJ IDEA也是這個公司的。它是專為大型軟體專案而設計,旨在改進Java,重點是可讀性,正確性和提升開發人員的生產力。 Kotlin是為了應對Java中的一些限制而建立的,這些限制阻礙了JetBrains軟體產品的開發,並且對於其它所有JVM語言的評估也被證明是不合適的。 由於Kotlin的目標是用於改進產品,因此它非常強調與Java程式碼和Java標準庫的互操作。

####特性 以下是為Android提供最大價值的特性。並解決了困擾客戶端應用程式開發的特定問題。 有關特性的全面列表,請參閱官方Kotlin參考文件

  1. 互操作性 Kotlin語言和執行時間的最重要特徵是其核心關注互操作性。與其他JVM替代語言(特別是Scala)不同,Kotlin能夠輕鬆地呼叫Java,並且Java輕鬆地呼叫Kotlin。事實上,你絕不會知道你正在向任何一個方向跨越邊界。Kotlin的執行時只是為了支援語言特性,使其非常精益化。Java標準庫型別,集合等都被重用,最終通過一些後續提到的特性增加了更多的實用性。(更多有關資訊,請參閱Kotlin文件)

  2. Lambdas 在此不做介紹。(更多有關資訊,請參閱Kotlin文件)

  3. 空型別安全 我們最好的朋友null是Kotlin系統型別的頭等型別。型別知道它們的可空性,並且在流控制和解引用中都受到特殊的處理。

val x: String? = "Hi"
x.length // 編譯不通過
val y: String = null // 編譯不通過
//y 是null值是不可避免的, 但有很多方法可以處理它.
if (x != null) {
  x.length // 編譯通過! 不符合習慣,只是為了獲取長度!
}
// 與上面的相同(IntelliJ 建議使用的).
x?.length
// Elvis 操作符.
val len = x?.length ?: -1
val len = x!!.length // 如果為null將丟擲空指標異常,很少使用。
複製程式碼

型別系統中有null值就像在Java中一樣,是對可空性註解有很大優勢的。在這種情況下,IDE和編譯器都嚴格執行契約而不是僅僅是提示。 通過將可空性推送到型別系統中,不需要諸如可選的傳統解決方法。這在Android上尤其重要,因為它的堆和垃圾收集器對於微小的和/或短生命週期的物件更加敏感。Java 10將把可選引入堆疊,但我們在Android看到之都要等死了。 由於上述堆和GC問題,Android使用了大量的null。像很多情況一樣,由於JAVA中所有的引用都可能為空,所以Android程式碼通常會被不必要的null檢查或者由於取消引用某些不被認為是null的錯誤而導致崩潰。將其移動到型別系統中將消除這種歧義,消除嘈雜,不必要的檢查和大多數疏忽的異常。(更多相關資訊,請參閱Kotlin文件

4.擴充方法 這類似於C#的方式,Kotlin允許將靜態和例項方法宣告為不能控制的型別,包括來自Java標準庫。然而,與C#不同的是,這些方法使用匯入方式進行靜態解析,提供了它們的起源的透明度(就像在實用程式類中靜態匯入的輔助方法一樣)。

fun String.last() : Char {
  return this[length - 1] // 為陣列構建擴充
}

val x = "Hey!"
println(x.last()) // 列印 "!".
複製程式碼

Guava的一半和Cash app的三分之二是由靜態工具方法組成。雖然這不會消除他們的存在,但它將允許您直接使用它們實現它們的型別。這是可讀性的一大勝利。(更多相關資訊,請參閱Kotlin文件

5.資料類 類似於JAVA10將要實現的值型別,資料類是僅存在於以語義,不可變型別分組資料的類。 我們目前使用AutoValue輕鬆模擬值型別。 data class Money(val currency: String, val amount: Int) 這個類將會帶給你equals, hashCode, toString 方法。每個元件以相同名稱的只讀屬性公開。 還有一種將值更改為新例項的copy方法。 val money = Money("USD", 100) val moreMoney = money.copy(amount = 200)//amount被重新賦值 可以通過多重分配解壓縮例項。 這類似於Python元組,並且已經被運送到標準庫中,例如在迴圈對映時用於Map.Entry。

for ((key, value) in map) {
  println(key + ": " + value)
}
複製程式碼

(更多相關資訊,請參閱Kotlin文件)

6.其他一些了不起的特性

  • 預設情況下類和方法是final的。如果你想擴充可以宣告他們open。
class Foo {}
class Bar extends Foo {} //編譯不通過
open class Foo {}
class Bar extends Foo {} // 編譯成功!
複製程式碼

(更多相關資訊,請參閱Kotlin文件

  • 隱式轉換。如果型別檢查成功,則變數則是更具體的型別。
val x: Object = "hi"
val length = x.length // 編譯不通過
if (x is String) {
  val length = x.length // Compiles!
}
複製程式碼

這也適用於可空性。

val x: Object? = "Hi"
if (x != null) {
  val y: Object = x // 'x' is a non-null type here
}
複製程式碼

(更多相關資訊,請參閱Kotlin文件

  • Delegates.observable()接受兩個引數:初始值和修改的處理程式。 每次分配給該屬性(執行分配之後)呼叫處理程式。 處理程式有三個引數:一個屬性被分配給,舊的值和新的一個: val lazy: String by Delegates.lazy { expensiveOperation() } (更多相關資訊,請參閱Kotlin文件

  • JetBrains正在積極的支援Square專案。最近,Retrofit和Dragger的執行已經被支援。 然而,Kotlin的很多語言功能消除了註釋處理器的需要。 例如,我可以使用委託屬性重新實現大多數ButterKnife作為執行時庫。

####用例 使用JAVA開發Square Cash Android應用程式存在痛點以及Kotlin的功能如何改善情況時存在的一些具體例子。

  • 實用方法 所謂的靜態實用方法丟棄了我們的程式碼庫。存在大量圖書館,如Guava,commons-lang等,以提供這些簡化與指定型別的常見互動的方法。 科特林並沒有消除這些實用方法 - 它對他們進行了增強! 每個人都有他們希望被內建的型別像String的方法。
fun String.truncateAt(max: Int) : String {
  return substring(0, Math.min(length, max))
}
複製程式碼

呼叫程式碼獲得語義上更有意義的呼叫: val name = "Jake Wharton".truncateAt(4) 這個例子是微不足道的,但是任何在合理的時間內編寫Java的人都可以推斷出這將對程式碼的清晰度有多大的影響。 值得注意的另一個具體例子是從協議緩衝區模式定義自動生成的型別。 即使我們在原始碼樹中擁有這些型別,但是它們的生成事實阻止了我們有意義的方法來擴充套件它們的有用方法(您在哪些部分類?)。 Kotlin提升這些實用方法直接對生成的型別進行操作。

fun Money.add(other: Money): Money {
  if (currency_code != other.currency_code) {
    throw IllegalArgumentException("Currency code ${other.currency_code}"
        + " does not match ${currency_code}.") // Hey String interpolation!
  }
  return copy(amount = amount + other.amount)
}
複製程式碼

現在我們可以像我們真正想要的那樣新增錢。

val one = Money("USD", 100)
val two = Money("USD", 200)
val three = one.add(two)
複製程式碼

但等等,還有更多!現在訂購,您還將收到操作員過載(只需支付單獨的運送和處理費用)。 如果我將上述方法重新命名為加號,我可以像任何其他值型別一樣新增這些例項。 val three = one + two 獎金:我可以把游標放在加號上,並按照任何其他方法命中CMD + B,直接進行擴充套件方法的實現! 記住,使用這些方法(包括操作符過載示例)取決於靜態匯入。 與C#不同,這些都不是神奇地應用到處。

  • RxJava, Listeners 幾乎所有的Android應用程式本身都是非同步的。 這導致程式碼由回撥,偵聽器和處理RxJava的反應流(一種通過它們管理非同步資料流的強大機制)組成的程式碼。
buttonView.setOnClickListener(new OnClickListener() {
  @Override public void onClick(View v) {
    finish();
  }
});
複製程式碼

現在,lambdas的優點應該是一般性的知識,但Android在接下來的兩年中不太可能會看到Java 8,即使只能在最新版本上使用。 Kotlin現在和所有版本的Android都提供給我們。 buttonView.setOnClickListener { finish() } 當您開始使用RxJava構建非同步資料流時,可以將數百行程式碼減少到10以下。程式碼的實際行為不會改變。 只有通過匿名類,長泛型型別宣告和中間值型別的詳細建立才能消除過多的樣板。

####練習

附上自己的一個kotlin 練習專案, 一個十分簡單天氣app。 https://github.com/zyl409214686/WeatherForKotlin

效果圖

相關文章