本文由微信開發團隊工程是由“oneliang”原創發表于WeMobileDev公眾號,內容稍有改動。
1、引言
Kotlin 是一個用于現代多平臺應用的靜態編程語言,由 JetBrains 開發(也就是開發了號稱Java界最智能的集成開發工具IntelliJ IDEA的公司)。Kotlin可以編譯成Java字節碼(就像Groovy和Scala一樣),也可以編譯成JavaScript,方便在沒有JVM的設備上運行。Kotlin已于2017年的Google I/O開發者大會上正式被宣布為Android官方支持開發語言(見《[資訊] Kotlin成為Android官方開發語言!》)。
有人說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而已。
Google官方已在各種場合直接或間接地表明了對于Kotlin和Java的態度——那就是Kotlin是 “Over” Java的(即可以理解為Kotlin在ANdroid中的定位是高于Java的)。所以,不管Android開發者有沒有做好準備,或者還在糾結要不要學習Kotlin時,都不影響Kotlin在Android中的定位和越來越明確的地位。但無論如何,對于Android開發者來說,多學一門技術確實很痛苦,但提前做好準備是更明智之選,至少到了Kotlin真的取代Java的那一天,而不至于后懂準備地太晚。
作為移動端即時通訊IM應用的王者——微信,為了始終保持技術的領先性,無論日后Kotlin在微信客戶中的重要性幾何,技術團隊做好技術儲備和預研實踐是肯定有必要的,于是便有了本文的整理和分享,希望業界共同學習、互相交流。
(本文同步發布于:http://www.52im.net/thread-2066-1-1.html)
2、概述
微信訂閱號助手的Android App項目首次嘗試使用Kotlin進行大規模的業務開發(483個Kt文件,3.8W行不包含空行的Kt代碼),一開始接觸Kotlin的時候難免會有點不適應,但經過幾天的強制使用后,慢慢有些感覺,項目落地后回顧了一下,發現Kotlin確實是有它獨特的風味。
什么是微信訂閱號助手?
微信公眾平臺“訂閱號助手”APP已正式上架App Store,通過這款訂閱號助手APP,公眾號運營者可以快捷地編輯和發表內容、方便地處理留言和回復粉絲消息。
訂閱號助手app能將你的iPhone變成一個隨身的公眾號“工作室”,無論身處何地,你都可以發表內容、與讀者互動。訂閱號助手app簡潔的編輯工具讓每個人輕松變身為作者,留住即刻的靈感,盡享內容創作的樂趣。訂閱號助手app讓每個有才華的個體都有機會被關注,都有自己的品牌。
3、“烹飪”準備
食材:
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
https://www.oracle.com/java
4、“烹飪”過程
1)開火,放少量食用油;
2)先把Android倒進去,伴兩下;
3)倒少量Java,主要是"字節碼"和"工具部分",再伴兩下;
4)把切好塊的Kotlin一塊塊慢慢平鋪在Android上面,把Android蓋住;
5)慢火煮3-5分鐘,觀察一下這個過程:
Kotlin把Android的味道慢慢釋放出來,比Android + Java更香;
Kotlin與Java融為一體 (前提是少量Java,如果Java放得太多,香味會受影響,粘合不夠好,容易松散(NPE));
6)關火,燜一會。
5、開鍋,上菜
色香味倶全,敬請盡情享受這番獨特的風味。
5.1 特色風味一:食用安全
食用安全,Nullable or NotNul從源頭抓起。
Kotlin代碼安全性更強:
varoutput: String
output = null// Compilation error
val name: String? = null// Nullable type
println(name.length()) // Compilation error
食用安全從從源頭上抓起,只要跟定義不符就編譯不通過,這是Kotlin小而精的一個優點,一下子能把整碟"菜"的安全系數提高,此Code來自官方文檔。
5.2 特色風味二:鮮
擴展函數,味道鮮美,百吃不厭。
項目工具類的另一種寫法:
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)對定義函數者的要求高了:正因體現了函數的類歸屬,也就使得開發者在定義函數的時候需要考慮歸屬給哪個類還是頂層函數這些問題,歸屬的范圍少了,會導致不好用,范圍廣了又怕暴露導致濫用或者誤用。
5.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("新標題", "新內容")
這種重載方式有效地減少我們項目中的重載方法數量,使得我們項目開發更簡潔和更有效率 ,自然就回味無窮。
5.4 特色風味四:甜而不膩
帶了糖,甜而不膩。
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。
6、如何更好地了解Kotlin這種食材的味道
Kotlin用于Java領域,中間產物毫無疑問還是字節碼,因此本質還是Java的基礎知識,反編譯Kotlin生成的字節碼是學習Kotlin一種較好的方式,可利用AndroidStudio的Tools來反編譯kt,能幫助快速理解Kotlin。
謝謝品嘗這份美味,希望Kotlin這款食材能帶給各位讀者不少Android上的特色的風味。
附錄:QQ、微信團隊原創技術文章
《微信朋友圈千億訪問量背后的技術挑戰和實踐總結》
《騰訊技術分享:騰訊是如何大幅降低帶寬和網絡流量的(圖片壓縮篇)》
《騰訊技術分享:騰訊是如何大幅降低帶寬和網絡流量的(音視頻技術篇)》
《微信團隊分享:微信移動端的全文檢索多音字問題解決方案》
《騰訊技術分享:Android版手機QQ的緩存監控與優化實踐》
《微信團隊分享:iOS版微信的高性能通用key-value組件技術實踐》
《微信團隊分享:iOS版微信是如何防止特殊字符導致的炸群、APP崩潰的?》
《騰訊技術分享:Android手Q的線程死鎖監控系統技術實踐》
《微信團隊原創分享:iOS版微信的內存監控系統技術實踐》
《讓互聯網更快:新一代QUIC協議在騰訊的技術實踐分享》
《iOS后臺喚醒實戰:微信收款到賬語音提醒技術總結》
《騰訊技術分享:社交網絡圖片的帶寬壓縮技術演進之路》
《微信團隊分享:視頻圖像的超分辨率技術原理和應用場景》
《微信團隊分享:微信每日億次實時音視頻聊天背后的技術解密》
《QQ音樂團隊分享:Android中的圖片壓縮技術詳解(上篇)》
《QQ音樂團隊分享:Android中的圖片壓縮技術詳解(下篇)》
《騰訊團隊分享:手機QQ中的人臉識別酷炫動畫效果實現詳解》
《騰訊團隊分享 :一次手Q聊天界面中圖片顯示bug的追蹤過程分享》
《微信團隊分享:微信Android版小視頻編碼填過的那些坑》
《微信手機端的本地數據全文檢索優化之路》
《企業微信客戶端中組織架構數據的同步更新方案優化實戰》
《微信團隊披露:微信界面卡死超級bug“15。。。。”的來龍去脈》
《QQ 18年:解密8億月活的QQ后臺服務接口隔離技術》
《月活8.89億的超級IM微信是如何進行Android端兼容測試的》
《以手機QQ為例探討移動端IM中的“輕應用”》
《一篇文章get微信開源移動端數據庫組件WCDB的一切!》
《微信客戶端團隊負責人技術訪談:如何著手客戶端性能監控和優化》
《微信后臺基于時間序的海量數據冷熱分級架構設計實踐》
《微信團隊原創分享:Android版微信的臃腫之困與模塊化實踐之路》
《微信后臺團隊:微信后臺異步消息隊列的優化升級實踐分享》
《微信團隊原創分享:微信客戶端SQLite數據庫損壞修復實踐》
《騰訊原創分享(一):如何大幅提升移動網絡下手機QQ的圖片傳輸速度和成功率》
《騰訊原創分享(二):如何大幅壓縮移動網絡下APP的流量消耗(下篇)》
《騰訊原創分享(三):如何大幅壓縮移動網絡下APP的流量消耗(上篇)》
《微信Mars:微信內部正在使用的網絡層封裝庫,即將開源》
《如約而至:微信自用的移動端IM網絡層跨平臺組件庫Mars已正式開源》
《開源libco庫:單機千萬連接、支撐微信8億用戶的后臺框架基石 [源碼下載]》
《微信新一代通信安全解決方案:基于TLS1.3的MMTLS詳解》
《微信團隊原創分享:Android版微信后臺保活實戰分享(進程?;钇?》
《微信團隊原創分享:Android版微信后臺?;顚崙鸱窒?網絡保活篇)》
《Android版微信從300KB到30MB的技術演進(PPT講稿) [附件下載]》
《微信團隊原創分享:Android版微信從300KB到30MB的技術演進》
《微信技術總監談架構:微信之道——大道至簡(演講全文)》
《微信技術總監談架構:微信之道——大道至簡(PPT講稿) [附件下載]》
《如何解讀《微信技術總監談架構:微信之道——大道至簡》》
《微信海量用戶背后的后臺系統存儲架構(視頻+PPT) [附件下載]》
《微信異步化改造實踐:8億月活、單機千萬連接背后的后臺解決方案》
《微信朋友圈海量技術之道PPT [附件下載]》
《微信對網絡影響的技術試驗及分析(論文全文)》
《一份微信后臺技術架構的總結性筆記》
《架構之道:3個程序員成就微信朋友圈日均10億發布量[有視頻]》
《快速裂變:見證微信強大后臺架構從0到1的演進歷程(一)》
《快速裂變:見證微信強大后臺架構從0到1的演進歷程(二)》
《微信團隊原創分享:Android內存泄漏監控和優化技巧總結》
《全面總結iOS版微信升級iOS9遇到的各種“坑”》
《微信團隊原創資源混淆工具:讓你的APK立減1M》
《微信團隊原創Android資源混淆工具:AndResGuard [有源碼]》
《Android版微信安裝包“減肥”實戰記錄》
《iOS版微信安裝包“減肥”實戰記錄》
《移動端IM實踐:iOS版微信界面卡頓監測方案》
《微信“紅包照片”背后的技術難題》
《移動端IM實踐:iOS版微信小視頻功能技術方案實錄》
《移動端IM實踐:Android版微信如何大幅提升交互性能(一)》
《移動端IM實踐:Android版微信如何大幅提升交互性能(二)》
《移動端IM實踐:實現Android版微信的智能心跳機制》
《移動端IM實踐:WhatsApp、Line、微信的心跳策略分析》
《移動端IM實踐:谷歌消息推送服務(GCM)研究(來自微信)》
《移動端IM實踐:iOS版微信的多設備字體適配方案探討》
《信鴿團隊原創:一起走過 iOS10 上消息推送(APNS)的坑》
《騰訊信鴿技術分享:百億級實時消息推送的實戰經驗》
《IPv6技術詳解:基本概念、應用現狀、技術實踐(上篇)》
《IPv6技術詳解:基本概念、應用現狀、技術實踐(下篇)》
《騰訊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)