本文由微信開發團隊工程是由「oneliang」原創發表於WeMobileDev公衆號,內容稍有改動。php
Kotlin 是一個用於現代多平臺應用的靜態編程語言,由 JetBrains 開發(也就是開發了號稱Java界最智能的集成開發工具IntelliJ IDEA的公司)。Kotlin能夠編譯成Java字節碼(就像Groovy和Scala同樣),也能夠編譯成JavaScript,方便在沒有JVM的設備上運行。Kotlin已於2017年的Google I/O開發者大會上正式被宣佈爲Android官方支持開發語言(見《[資訊] Kotlin成爲Android官方開發語言!》)。html
有人說Kolin對於Android的做用,是否是Swift對於iOS的做用同樣(主要用於下降Objective-C開發門檻等)。實際上,Kotlin對於Android的意義和重要性要遠大於Swift對於iOS,由於無論是Objective-C仍是Swift,它們至少都是蘋果自已的東西,而悲劇的是Java並不屬於Google。鑑於Google和Oracle(Java的創造者SUN公司早就被Oracle收購了)的官司(見《[資訊] Java侵權案逆轉:Google需賠88億!》),如何解決掉Java這個如鯁在喉的歷史遺留,是Android決策者早就在考慮的問題,只是剛好選中了Kotlin而已。java
Google官方已在各類場合直接或間接地代表了對於Kotlin和Java的態度——那就是Kotlin是 「Over」 Java的(便可以理解爲Kotlin在ANdroid中的定位是高於Java的)。因此,無論Android開發者有沒有作好準備,或者還在糾結要不要學習Kotlin時,都不影響Kotlin在Android中的定位和愈來愈明確的地位。但不管如何,對於Android開發者來講,多學一門技術確實很痛苦,但提早作好準備是更明智之選,至少到了Kotlin真的取代Java的那一天,而不至於後懂準備地太晚。android
做爲移動端即時通信IM應用的王者——微信,爲了始終保持技術的領先性,不管往後Kotlin在微信客戶中的重要性幾何,技術團隊作好技術儲備和預研實踐是確定有必要的,因而便有了本文的整理和分享,但願業界共同窗習、互相交流。程序員
(本文同步發佈於:http://www.52im.net/thread-2066-1-1.html)算法
微信訂閱號助手的Android App項目首次嘗試使用Kotlin進行大規模的業務開發(483個Kt文件,3.8W行不包含空行的Kt代碼),一開始接觸Kotlin的時候不免會有點不適應,但通過幾天的強制使用後,慢慢有些感受,項目落地後回顧了一下,發現Kotlin確實是有它獨特的風味。數據庫
什麼是微信訂閱號助手?編程
微信公衆平臺「訂閱號助手」APP已正式上架App Store,經過這款訂閱號助手APP,公衆號運營者能夠快捷地編輯和發表內容、方便地處理留言和回覆粉絲消息。小程序
訂閱號助手app能將你的iPhone變成一個隨身的公衆號「工做室」,不管身處何地,你均可以發表內容、與讀者互動。訂閱號助手app簡潔的編輯工具讓每一個人輕鬆變身爲做者,留住即刻的靈感,盡享內容創做的樂趣。訂閱號助手app讓每一個有才華的個體都有機會被關注,都有本身的品牌。微信小程序
食材:
1)Android,主要食材(指Framework、Api等);
2)Kotlin,食用安全、味鮮(擴展函數)、香(重載)、甜(富含糖份Lambda),第二主要食材,切好塊狀;
3)Java,少許,Kotlin這種食材須要它來作引子。
鍋:
AndroidStudio、Eclipse這兩個牌子的鍋質量都不錯。
調味料:
Kotlin Android Extension、Android KTX、AndroidX、Anko等。
若是沒有上述這些材料請移步到以下網址"購買":
https://developers.google.com/android
https://kotlinlang.org/docs/reference
1)開火,放少許食用油;
2)先把Android倒進去,伴兩下;
3)倒少許Java,主要是"字節碼"和"工具部分",再伴兩下;
4)把切好塊的Kotlin一塊塊慢慢平鋪在Android上面,把Android蓋住;
5)慢火煮3-5分鐘,觀察一下這個過程:
Kotlin把Android的味道慢慢釋放出來,比Android + Java更香;
Kotlin與Java融爲一體 (前提是少許Java,若是Java放得太多,香味會受影響,粘合不夠好,容易鬆散(NPE));
6)關火,燜一會。
色香味倶全,敬請盡情享受這番獨特的風味。
食用安全,Nullable or NotNul從源頭抓起。
Kotlin代碼安全性更強:
varoutput: String
output = null// Compilation error
val name: String? = null// Nullable type
println(name.length()) // Compilation error
食用安全從從源頭上抓起,只要跟定義不符就編譯不經過,這是Kotlin小而精的一個優勢,一會兒能把整碟"菜"的安全係數提升,此Code來自官方文檔。
擴展函數,味道鮮美,百吃不厭。
項目工具類的另外一種寫法:
fun String.toIntSafely(defaultValue: Int = 0): Int {
returntry{
this.toInt()
} catch(e: Exception) {
defaultValue
}
}
fun main(args: Array<String>) {
println("1".toIntSafely())
}
String 轉 Int,這種需求幾乎不少項目都是須要,像上述Kotlin若是是在Java裏面描述的話,估計會寫成這樣:
public final class StringUtil{
private StringUtil() {}
public static int stringToInt(String string, int defaultValue) {
//省略
}
}
使用時:
StringUtil.stringToInt("1", 0);
你們看到這裏可能會以爲沒什麼,你們都是工具類,用的時候有些小差異而已。
但正由於這些小差異,優勢就體現出來了,確實是鮮美:
1)不須要記住工具類的名字和方法的名字:假如你是一個剛接手項目的新人,正準備作一個需求開發,忽然須要這種String to Int的工具,可是不知道工具在哪,這就比如你去到一個陌生人的家裏,想找個螺絲刀擰個鬆掉的螺絲同樣,這「螺絲刀」在哪?除了問「主人」以外,要麼就是「翻櫃子」,這不就顯得效率低麼?使用Kotlin的擴展函數就能有效避免前面所說的問題,接手項目的新人只須要輕輕的「.」一下,滾兩下鼠標,"toIntSafely"的方法就會看到。這就爲何你看Kotlin的Java擴展庫不少都是經過擴展函數來封裝;
2)方法的類歸屬更好理解:以上述的"toIntSafely"爲例,String.toIntSafely,使得開發者更容易直觀感覺到這個函數是用於String,不像StringUtil.stringToInt沒有歸屬可言,純粹就是一個工具函數,不如Kotlin的寫法容易理解;
3)對定義函數者的要求高了:正因體現了函數的類歸屬,也就使得開發者在定義函數的時候須要考慮歸屬給哪一個類仍是頂層函數這些問題,歸屬的範圍少了,會致使很差用,範圍廣了又怕暴露致使濫用或者誤用。
重載(Overload),耐人尋味。
雖然這個概念在面向對象領域用得不少,但Kotlin這個重載的味道真是令咱們吃上癮。
重載在工具類的場景用得很是多,一個項目下來沒工具類也是不可能。
例如咱們在項目中會封裝一些對話框(Dialog)工具類供開發的同窗一句調用:
1)開發的同窗須要在界面顯示一個Dialog,只想改變Dialog的內容,那麼Java裏面就有showDialog(String message)的寫法;
2)開發的同窗須要在界面顯示一個Dialog,即想改變Dialog的標題,又想改變Dialog的內容,那麼Java裏面就有showDialog(String title, String message)的寫法;
3)開發的同窗想改變Dialog裏面Icon的....
4)開發的同窗想......
這些場景估計作Android開發的同窗都會碰到,其實不限於Android,Java開發的同窗也常常遇到。
咱們看看Kotlin是怎樣把這些需求收攏:
fun showDialog(title: String = "標題", message: String = "內容") {
//TODO
}
這個寫法一會兒知足 2的2次方(4) 種重載方法:
showDialog()
showDialog("新標題")
showDialog(message = "新內容")
showDialog("新標題", "新內容")
這種重載方式有效地減小咱們項目中的重載方法數量,使得咱們項目開發更簡潔和更有效率 ,天然就耐人尋味。
帶了糖,甜而不膩。
Kotlin裏面Function與Lambda既可相互理解,又有其味道(寫法)上的一些差別。
味道 (結果) 同樣,但味道消去的過程 (用法) 有差異。
Function(函數)經常使用寫法:
fun f(x: Int): Any {
returnAny()
}
用法:
val y = f(1)
Function(函數)的一種Lambda寫法:
fun f() = { x: Int -> Any() } 等價於 fun f(): (Int) -> Any = { x: Int -> Any() }
用法:
val y = f()(1) 或 val y = f().invoke(1)
Lambda寫法:
val f = { x: Int -> Any() } 等價於 val f: (Int) -> Any = { x: Int -> Any }
用法:
val y = f(1) 或 val y = f.invoke(1)
細節點:Function時,有"="跟沒有"="意義不同,有"="的時候能夠理解右邊( { x: Int -> Any() } )是 左邊函數返回類型((Int) -> Any) 的實現。
函數不用置疑,項目裏面必備。
Lambda:
Lambda,語法糖,這是怎樣的一種成份?
Lambda是長這樣的:
val block: () -> Unit = {}
val sum: (Int, Int) -> Int = { p1, p2 -> p1 + p2 }
Lambda令咱們的項目減小了不少接口類,尤爲是回調接口,咱們項目幾乎沒有。通常的業務場景裏面回調接口都會用得很多,Lambda能有效減小這種Callback接口的定義,少寫很多接口類,事半功倍。
另lambda裏面不能寫return,最後一行的值就是返回值。
從數學函數角度抽象理解:
函數: y = f(x)
〉假設x與y都是Int類型
能夠理解爲 Kotlin 函數:
fun f(x: Int): Int {
return1 // 這裏的返回值就是對應y
}
也能夠理解爲 Lambda:
val f = { x: Int -> 1 } 等價於 val f: (Int) -> Int = { x: Int -> 1 }
使用時f(1),可是若是像上述那種f(x)的kotlin函數與f(x)的lambda同時同名同方法簽名存在,使用上要f(1)與f.invoke(1)來區分是函數調用仍是lambda調用。
〉假設x與y都是Lambda類型
x是Lambda類型 (Int) -> Int ,y是Lambda類型 (Int) -> Int,能夠換算成:
fun f(x: (Int) -> Int): (Int) -> Int {
return{ it -> x(it) }
}
或這樣:
fun f(x: (Int) -> Int): (Int) -> Int = { it -> x(it) }
使用時:
f { it -> it + 10 }(1) or f { it -> it + 10 }.invoke(1)
或 Lambda:
val f: ((Int) -> Int) -> ((Int) -> Int) = { x -> { it -> x(it) } } // val時要inline
使用時:
f.invoke { it -> it + 10 }.invoke(1)
經過上述的 替換 能更好地理解和使用Lambda。
Kotlin用於Java領域,中間產物毫無疑問仍是字節碼,所以本質仍是Java的基礎知識,反編譯Kotlin生成的字節碼是學習Kotlin一種較好的方式,可利用AndroidStudio的Tools來反編譯kt,能幫助快速理解Kotlin。
謝謝品嚐這份美味,但願Kotlin這款食材能帶給各位讀者很多Android上的特點的風味。
《騰訊技術分享:騰訊是如何大幅下降帶寬和網絡流量的(圖片壓縮篇)》
《騰訊技術分享:騰訊是如何大幅下降帶寬和網絡流量的(音視頻技術篇)》
《騰訊技術分享:Android版手機QQ的緩存監控與優化實踐》
《微信團隊分享:iOS版微信的高性能通用key-value組件技術實踐》
《微信團隊分享:iOS版微信是如何防止特殊字符致使的炸羣、APP崩潰的?》
《騰訊技術分享:Android手Q的線程死鎖監控系統技術實踐》
《QQ音樂團隊分享:Android中的圖片壓縮技術詳解(上篇)》
《QQ音樂團隊分享:Android中的圖片壓縮技術詳解(下篇)》
《騰訊團隊分享 :一次手Q聊天界面中圖片顯示bug的追蹤過程分享》
《微信團隊分享:微信Android版小視頻編碼填過的那些坑》
《微信團隊披露:微信界面卡死超級bug「15。。。。」的前因後果》
《月活8.89億的超級IM微信是如何進行Android端兼容測試的》
《微信客戶端團隊負責人技術訪談:如何着手客戶端性能監控和優化》
《微信團隊原創分享:Android版微信的臃腫之困與模塊化實踐之路》
《微信團隊原創分享:微信客戶端SQLite數據庫損壞修復實踐》
《騰訊原創分享(一):如何大幅提高移動網絡下手機QQ的圖片傳輸速度和成功率》
《騰訊原創分享(二):如何大幅壓縮移動網絡下APP的流量消耗(下篇)》
《騰訊原創分享(三):如何大幅壓縮移動網絡下APP的流量消耗(上篇)》
《如約而至:微信自用的移動端IM網絡層跨平臺組件庫Mars已正式開源》
《開源libco庫:單機千萬鏈接、支撐微信8億用戶的後臺框架基石 [源碼下載]》
《微信新一代通訊安全解決方案:基於TLS1.3的MMTLS詳解》
《微信團隊原創分享:Android版微信後臺保活實戰分享(進程保活篇)》
《微信團隊原創分享:Android版微信後臺保活實戰分享(網絡保活篇)》
《Android版微信從300KB到30MB的技術演進(PPT講稿) [附件下載]》
《微信團隊原創分享:Android版微信從300KB到30MB的技術演進》
《微信技術總監談架構:微信之道——大道至簡(PPT講稿) [附件下載]》
《微信海量用戶背後的後臺系統存儲架構(視頻+PPT) [附件下載]》
《微信異步化改造實踐:8億月活、單機千萬鏈接背後的後臺解決方案》
《架構之道:3個程序員成就微信朋友圈日均10億發佈量[有視頻]》
《微信團隊原創分享:Android內存泄漏監控和優化技巧總結》
《微信團隊原創Android資源混淆工具:AndResGuard [有源碼]》
《移動端IM實踐:Android版微信如何大幅提高交互性能(一)》
《移動端IM實踐:Android版微信如何大幅提高交互性能(二)》
《移動端IM實踐:WhatsApp、Line、微信的心跳策略分析》
《移動端IM實踐:谷歌消息推送服務(GCM)研究(來自微信)》
《信鴿團隊原創:一塊兒走過 iOS10 上消息推送(APNS)的坑》
《騰訊TEG團隊原創:基於MySQL的分佈式數據庫TDSQL十年鍛造經驗分享》
《微信多媒體團隊訪談:音視頻開發的學習、微信的音視頻技術和挑戰等》
《瞭解iOS消息推送一文就夠:史上最全iOS Push技術詳解》
《騰訊資深架構師乾貨總結:一文讀懂大型分佈式系統設計的方方面面》
《騰訊音視頻實驗室:使用AI黑科技實現超低碼率的高清實時視頻聊天》
《騰訊技術分享:微信小程序音視頻與WebRTC互通的技術思路和實踐》
《手把手教你讀取Android版微信和手Q的聊天記錄(僅做技術研究學習)》
《微信技術分享:微信的海量IM聊天消息序列號生成實踐(算法原理篇)》
《微信技術分享:微信的海量IM聊天消息序列號生成實踐(容災方案篇)》
《騰訊技術分享:GIF動圖技術詳解及手機QQ動態表情壓縮技術實踐》
《微信團隊分享:Kotlin漸被承認,Android版微信的技術嚐鮮之旅》
>> 更多同類文章 ……
(本文同步發佈於:http://www.52im.net/thread-2066-1-1.html)