本書詳細(xì)介紹了Kotlin語言方方面面的特性,包括各種類型的函數(shù),貫徹本書始終的Lambda表達(dá)式,有別于Java的委托、泛型,靈活、簡潔的DSL,常用的語法糖,相比線程更加輕量級的協(xié)程,參考RxJava實現(xiàn)的Flow,等等。本書還提供了大量涉及移動端、服務(wù)端甚至桌面端的案例,這些案例都是編者使用Kotlin之后的實踐和心得,同時包含很多編者封裝的library,供讀者參考、借鑒和使用。 本書適合有一定Kotlin語法基礎(chǔ)的讀者使用,尤其適合移動端和服務(wù)端的開發(fā)人員使用,也可以用作大專院校和培訓(xùn)機(jī)構(gòu)的教學(xué)參考書。
本書幾乎涵蓋了Kotlin所有的特性,包括函數(shù)特性、面向?qū)ο筇匦、元編程、DSL、跨平臺開發(fā)、協(xié)程、Flow、RxJava、Jetpack等,內(nèi)容非常豐富。
本書還介紹了使用Kotlin開發(fā)的多個實例,如移動端實戰(zhàn)、服務(wù)端實戰(zhàn)、響應(yīng)式開發(fā)實戰(zhàn)等,這些例子是對本書知識的綜合運(yùn)用,對使用Kotlin進(jìn)行開發(fā)的讀者具備較大的參考價值。
本書是編者系統(tǒng)學(xué)習(xí)Kotlin和多年實戰(zhàn)經(jīng)驗的積累和總結(jié),通過非常簡易的代碼講解Kotlin語言的各種特性,代碼實例不會涉及過于抽象的業(yè)務(wù)場景,但會通過具體代碼實例對Kotlin語言背后的設(shè)計思想和原理進(jìn)行詳細(xì)分析,力圖使讀者通過實際操作快速上手和深入理解Kotlin語言的相關(guān)知識。
本書面向所有希望從事 Android 開發(fā)和服務(wù)端開發(fā)的IT從業(yè)人員,希望讀者通過閱讀本書,使用Kotlin開發(fā)應(yīng)用程序的技能更上一層樓。
Kotlin是一門務(wù)實的語言。Kotlin從發(fā)展之初就受到各種語言(例如Java、C#、JavaScript、Scala、Groovy、Python等)的影響,或者說Kotlin集各家語言之長,吸收了各種語言比較好的特性。在JVM環(huán)境下,Kotlin被設(shè)計成可以和Java代碼相互操作,并可以重復(fù)使用Java現(xiàn)有函數(shù)庫和框架的語言。
在2016年年底,筆者工作之余,開始研究Kotlin這門語言。順便嘗試使用Kotlin編寫一些Android上的組件。
隨后,在2017-2018年,筆者負(fù)責(zé)的移動端團(tuán)隊開始嘗試使用Kotlin編寫全新的App。此時恰逢谷歌宣布使用Kotlin作為Android的官方語言,這更加堅定了我們使用Kotlin的決心。個人也在此期間嘗試使用Kotlin來編寫服務(wù)端的程序。到了2019年年初,筆者跳槽到了萬物新生(當(dāng)時還是愛回收)的創(chuàng)新中心。在這里,我們服務(wù)端的主力語言就是Kotlin。使用Kotlin編寫后端服務(wù)在當(dāng)時甚至到現(xiàn)在都是一件比較酷的事情。
這些年來,筆者在兩家公司使用Kotlin做了很多項目,從App到桌面程序再到服務(wù)端程序,積累了很多相關(guān)的編程經(jīng)驗。因此編寫了本書,希望通過本書能讓讀者了解這門務(wù)實的語言,以及嘗試使用這門語言。Kotlin也是基于JVM的語言,上手不難,但是其思想跟Java大相徑庭。
每隔幾年,我們都會聽到一種聲音xxx語言將會取代Java,取代Java的語言也從之前的C#、PHP、Python變成了Go、Kotlin。其實,只要從TIOBE的榜單就可以看到,這些年來Java 一直占據(jù)著這份榜單前三的位置,甚至很多年來都是。Java龐大的生態(tài)系統(tǒng)、海量的項目決定了其在未來很多年內(nèi)不可能被取代。
題外話,在下一代的Java虛擬機(jī)Graal VM中,除了支持基于JVM的語言Java、Scala、Groovy、Kotlin等外,還支持JavaScript、Python、Ruby、R,以及基于LLVM的C、C 、Rust。Graal VM會讓Java變得更加強(qiáng)大。
Kotlin的出現(xiàn)是為了編寫更好的Java,Kotlin可以與Java進(jìn)行互操作,并且Kotlin有自己獨(dú)特的優(yōu)勢:
? 豐富的語法糖
? 強(qiáng)類型
? 函數(shù)式編程
? 協(xié)程
……
因此,Kotlin也被戲稱為Java好的第三方庫。
本書詳細(xì)介紹了Kotlin語言的各種特性,例如花了大量篇幅介紹各種類型的函數(shù),貫徹本書始終的Lambda表達(dá)式,有別于Java的委托、泛型,靈活、簡潔的DSL,常用的語法糖,相比線程更加輕量級的協(xié)程,參考RxJava實現(xiàn)的Flow,等等。
本書不僅介紹Kotlin的功能,還會對部分Kotlin特性進(jìn)行源碼解析,也會對各個特性進(jìn)行深入的總結(jié)。
另外,本書帶來了豐富的案例,涉及移動端、服務(wù)端甚至桌面端。它們都是筆者在大量使用 Kotlin之后的實踐和心得,同時包含很多筆者封裝的library,供讀者參考、借鑒和使用。因此,本書主要面向移動端、服務(wù)端的讀者。
本書編寫的時間跨度有一點(diǎn)長,歷經(jīng)了Kotlin 1.3到當(dāng)前的Kotlin 1.5。現(xiàn)在Kotlin已經(jīng)變成筆者的主力編程語言。當(dāng)然,Kotlin的研發(fā)團(tuán)隊也在不斷更新,據(jù)說每隔6個月會發(fā)布一個新版本,有點(diǎn)類似Java發(fā)布新版本的節(jié)奏。筆者也會不斷跟進(jìn)Kotlin新版本的特性。
總之,本書盡量多地介紹Kotlin方方面面的特性,用豐富的例子來增強(qiáng)說服力。本書共18章,其中第10、13、14、15(部分內(nèi)容)、17(部分內(nèi)容)章是由易龐宙編寫的,其余是由沈哲編寫的。本書的資源在GitHub中,地址為https://github.com/fengzhizi715/Advance-Kotlin-Tutorials。
當(dāng)然,在編寫本書的過程中,Kotlin也在不斷地更新、完善。另外,筆者才疏學(xué)淺,書中難免會有不當(dāng)之處,歡迎讀者批評指正,一起討論Kotlin的方方面面。
后,寫書是一個枯燥、漫長且耗費(fèi)大量時間、精力的事情,感謝清華大學(xué)出版社的編輯、我的同事、家人對我的幫助,特別是我的太太一直在我身后默默地為家庭付出。
沈 哲
2021年6月
沈 哲,現(xiàn)就職于萬物新生(愛回收),擔(dān)任創(chuàng)新中心技術(shù)總監(jiān),負(fù)責(zé)AIoT 產(chǎn)品相關(guān)的研發(fā)工作。具有多年的服務(wù)端、移動端研發(fā)經(jīng)驗,熟悉函數(shù)響應(yīng)式編程,對計算機(jī)視覺有一定的研究。曾負(fù)責(zé)過一款移動端深度鏈接的產(chǎn)品,日活數(shù)千萬,該產(chǎn)品已于2019年初以千萬級別的交易額賣給極光,后更名為極光魔鏈。出版著作《RxJava 2.x 實戰(zhàn)》。
易龐宙,Android開源愛好者,RxTask庫、全面屏適配庫以及一些Android常用開源工具的開發(fā)者,CSDN博主。負(fù)責(zé)過搜床科技集團(tuán)Android開發(fā),例如xbed、酒店自助入住App開發(fā)等,目前就職于廣州極飛科技股份有限公司,擔(dān)任高級Android開發(fā)工程師。
第1章 認(rèn)識Kotlin 1
1.1 Kotlin簡介 1
1.1.1 Kotlin的歷史 1
1.1.2 Kotlin的特性 1
1.2 Kotlin的發(fā)展 2
1.2.1 實用主義 2
1.2.2 生態(tài)圈 3
1.2.3 逐漸Kotlin化的Java 3
1.3 總結(jié) 3
第2章 Kotlin的函數(shù)與類 4
2.1 函數(shù)的基本概念 4
2.1.1 函數(shù)的參數(shù) 5
2.1.2 函數(shù) 8
2.2 Kotlin的類(一) 11
2.2.1 構(gòu)造函數(shù)和初始化塊 12
2.2.2 屬性 15
2.2.3 抽象類 16
2.2.4 嵌套類和內(nèi)部類 16
2.2.5 枚舉類 17
2.3 Kotlin的類(二) 18
2.3.1 對象聲明和對象表達(dá)式 18
2.3.2 伴生對象 19
2.3.3 數(shù)據(jù)類 20
2.3.4 密封類 23
2.4 總結(jié) 24
第3章 Kotlin的函數(shù)式編程 25
3.1 函數(shù)式編程與高階函數(shù) 25
3.1.1 函數(shù)式編程 25
3.1.2 高階函數(shù) 25
3.2 Lambda表達(dá)式 29
3.2.1 Java 8的Lambda 29
3.2.2 Kotlin的Lambda語法 31
3.2.3 簡化Kotlin的Lambda表達(dá)式 31
3.2.4 方法引用 32
3.2.5 Kotlin支持SAM轉(zhuǎn)換 33
3.2.6 使用高階函數(shù)的例子 34
3.2.7 換個角度看 Lambda表達(dá)式 35
3.3 集合、序列和Java中的流 38
3.3.1 集合中的函數(shù)式API 38
3.3.2 序列和流 41
3.4 總結(jié) 41
第4章 內(nèi)聯(lián)函數(shù)與擴(kuò)展函數(shù) 42
4.1 內(nèi)聯(lián)函數(shù) 42
4.1.1 inline的使用 42
4.1.2 禁用內(nèi)聯(lián)noinline 45
4.1.3 非局部返回以及crossinline的使用 47
4.2 內(nèi)聯(lián)屬性 48
4.2.1 內(nèi)聯(lián)屬性 48
4.2.2 內(nèi)聯(lián)類 48
4.3 擴(kuò)展函數(shù) 48
4.3.1 擴(kuò)展函數(shù)的特性 48
4.3.2 常用標(biāo)準(zhǔn)庫的擴(kuò)展函數(shù) 51
4.4 擴(kuò)展屬性 56
4.5 總結(jié) 60
第5章 委托 61
5.1 委托介紹 61
5.1.1 靜態(tài)代理 61
5.1.2 動態(tài)代理 62
5.2 Kotlin的委托模式和委托屬性 64
5.2.1 委托模式 64
5.2.2 委托屬性 65
5.3 lateinit和by lazy 69
5.4 總結(jié) 73
第6章 泛型 74
6.1 類型擦除 74
6.1.1 Java泛型的優(yōu)點(diǎn) 74
6.1.2 Kotlin的泛型 75
6.1.3 Java通過類型擦除支持泛型 75
6.1.4 Kotlin如何獲得聲明的泛型類型 77
6.2 型變 80
6.2.1 類和類型 80
6.2.2 型變 80
6.3 泛型約束、類型投影與星號投影 83
6.3.1 泛型約束 83
6.3.2 類型投影 84
6.3.3 星號投影 84
6.3.4 泛型的應(yīng)用 85
6.4 總結(jié) 86
第7章 元編程 87
7.1 元編程 87
7.1.1 元編程介紹 87
7.1.2 元編程的分類 87
7.1.3 根本沒有什么元編程,從來只有編程而已 88
7.2 Kotlin反射概述 88
7.2.1 概述 88
7.2.2 Kotlin反射API 89
7.3 Java反射和Kotlin反射(上) 90
7.3.1 類引用,獲取Class對象 90
7.3.2 構(gòu)造函數(shù)引用,獲取類的構(gòu)造函數(shù) 91
7.3.3 函數(shù)引用,獲取類的成員函數(shù) 92
7.3.4 屬性引用,獲取類的成員變量 94
7.4 Java反射和Kotlin反射(下) 96
7.4.1 獲取類的其他信息 96
7.4.2 Java反射與Kotlin反射的互操作性 98
7.5 總結(jié) 99
第8章 DSL的構(gòu)建 100
8.1 DSL介紹 100
8.2 構(gòu)建一個DSL的多種方式 101
8.2.1 帶接收者的函數(shù)類型 101
8.2.2 帶接收者的Lambda 101
8.2.3 創(chuàng)建一個自己的DSL 102
8.2.4 將擴(kuò)展函數(shù)改成DSL的方式 104
8.2.5 使用運(yùn)算符重載實現(xiàn)DSL 105
8.2.6 使用中綴表達(dá)式實現(xiàn)DSL 106
8.2.7 Kotlin DSL的實際使用封裝路由框架的使用 107
8.3 總結(jié) 108
第9章 常用語法糖與設(shè)計模式 110
9.1 運(yùn)算符重載 110
9.2 中綴表達(dá)式 112
9.2.1 在擴(kuò)展函數(shù)中使用中綴表達(dá)式 113
9.2.2 在成員函數(shù)中使用中綴表達(dá)式 113
9.3 作用域函數(shù) 114
9.3.1 作用域函數(shù)的概念 114
9.3.2 如何優(yōu)雅地使用作用域函數(shù) 114
9.4 Contract契約 118
9.4.1 Contract的概念 119
9.4.2 Contract的特性 119
9.4.3 Contract源碼解析 120
9.4.4 小結(jié) 122
9.5 在data class中使用MapStruct 122
9.5.1 data class的copy()為淺拷貝 122
9.5.2 MapStruct簡介 123
9.5.3 在Kotlin中使用MapStruct 123
9.6 更好地使用設(shè)計模式 126
9.6.1 單例模式 126
9.6.2 builder模式 127
9.6.3 觀察者模式 128
9.6.4 狀態(tài)模式 129
9.7 總結(jié) 130
第10章 跨平臺開發(fā) 131
10.1 跨平臺的簡單介紹 131
10.1.1 跨平臺開發(fā)的愿景 131
10.1.2 跨平臺開發(fā)當(dāng)前的主流技術(shù) 131
10.1.3 Kotlin與Flutter的對比 132
10.2 利用Ktor-Client實現(xiàn)跨平臺網(wǎng)絡(luò)請求 132
10.2.1 什么是Ktor 132
10.2.2 Ktor-Client的使用 132
10.3 總結(jié) 142
第11章 協(xié)程及其應(yīng)用 143
11.1 協(xié)程的基本概念 143
11.1.1 協(xié)程的定義 143
11.1.2 為何要使用協(xié)程 143
11.1.3 Kotlin協(xié)程的基本概念 148
11.2 Coroutine builders 149
11.2.1 launch和async 149
11.2.2 runBlocking 152
11.3 掛起函數(shù) 152
11.3.1 delay 152
11.3.2 yield 153
11.3.3 withContext 154
11.3.4 coroutineScope 156
11.4 協(xié)程的上下文和調(diào)度 156
11.4.1 協(xié)程的調(diào)度 156
11.4.2 父子協(xié)程 158
11.4.3 多個CoroutineContext進(jìn)行 操作 160
11.4.4 CoroutineContext Job 161
11.5 協(xié)程的作用域 CoroutineScope 162
11.5.1 盡量少用GlobalScope 162
11.5.2 安全地使用CoroutineScope 163
11.5.3 在Android中更好地使用Coroutines 163
11.6 Channel機(jī)制 164
11.6.1 生產(chǎn)者和消費(fèi)者 164
11.6.2 管道 165
11.6.3 channel緩沖 167
11.6.4 actor 168
11.6.5 Select表達(dá)式 169
11.7 總結(jié) 170
第12章 Flow的基本使用 171
12.1 Flow的使用 171
12.1.1 Kotlin Flow介紹 171
12.1.2 Flow的基本使用方式 171
12.1.3 Flow的生命周期 176
12.2 Flow和RxJava 177
12.2.1 Flow和Sequences 177
12.2.2 Flow和RxJava 178
12.3 Flow的異常處理 182
12.3.1 catch操作符 182
12.3.2 retry、retryWhen操作符 184
12.4 Flow的線程操作 185
12.4.1 更為簡化的線程切換 185
12.4.2 flowOn和RxJava的observeOn 185
12.4.3 buffer實現(xiàn)并發(fā)操作 186
12.4.4 并行操作 188
12.5 Flow其他的操作符 189
12.5.1 轉(zhuǎn)換操作符 189
12.5.2 限制大小的操作符 189
12.5.3 終端操作符 189
12.5.4 合并操作符 190
12.5.5 扁平化操作符 193
12.6 總結(jié) 195
第13章 RxJava的新特性及常用操作符 198
13.1 RxJava入門 198
13.1.1 RxJava入門理念 198
13.1.2 RxJava的基礎(chǔ)知識 199
13.1.3 RxJava的生命周期 201
13.2 RxJava 3新特性描述 204
13.2.1 主要特性講解 204
13.2.2 與RxJava 2.x的區(qū)別 204
13.2.3 RxJava 3新特性部分詳述 204
13.3 常用操作符講解 207
13.3.1 創(chuàng)建操作符 207
13.3.2 轉(zhuǎn)換操作符 215
13.3.3 過濾操作符 220
13.4 總結(jié) 227
第14章 RxJava的核心機(jī)制 229
14.1 ObservableSource、Observable、Observer的同流合污 229
14.2 恐怖的Function機(jī)制 230
14.3 線程的決策者Scheduler 231
14.3.1 Scheduler工作核心Worker 232
14.3.2 Scheduler線程池核心RxThreadFactory 232
14.3.3 異步實踐例子 233
14.3.4 并行的操作 234
14.4 Observeable五兄弟的差異性 235
14.4.1 Observable 235
14.4.2 Flowable 238
14.4.3 Single 239
14.4.4 Completable 240
14.4.5 Maybe 240
14.5 背壓策略 241
14.5.1 MISSING 242
14.5.2 ERROR 242
14.5.3 BUFFER 242
14.5.4 DROP 243
14.5.5 LATEST 243
14.6 總結(jié) 243
第15章 Jetpack 244
15.1 Jetpack介紹 244
15.1.1 客戶端的架構(gòu)迭代 244
15.1.2 AAC的功能 246
15.1.3 Android Jetpack 247
15.2 Lifecycle 249
15.2.1 Lifecycle介紹 249
15.2.2 Lifecycle的使用 250
15.2.3 Retrofit結(jié)合Lifecycle 253
15.3 ViewModel 254
15.3.1 ViewModel介紹 254
15.3.2 ViewModel的使用 255
15.3.3 使用Kotlin委托屬性創(chuàng)建ViewModel 256
15.3.4 AndroidViewModel 257
15.3.5 ViewModel源碼簡單分析 257
15.4 LiveData 261
15.4.1 LiveData介紹 261
15.4.2 LiveData的使用 262
15.4.3 在ViewModel中使用LiveData 263
15.4.4 LiveData實現(xiàn)Fragment之間的通信 264
15.4.5 LiveData源碼簡單分析 265
15.5 Room的用法 267
15.5.1 Room的基本了解 267
15.5.2 Room的配置與使用 268
15.5.3 常用的SQL操作 270
15.5.4 Room的兼容與升級 271
15.5.5 小結(jié) 275
15.6 Navigation用法詳解 276
15.6.1 Navigation的配置 276
15.6.2 Navigation的基本使用 277
15.6.3 Navigation原理解析 284
15.6.4 小結(jié) 287
15.7 總結(jié) 287
第16章 Android實戰(zhàn) 288
16.1 構(gòu)建一個日志框架 288
16.1.1 Android日志框架L 288
16.1.2 如何開發(fā)一款類似L的日志框架 289
16.1.3 記錄Android日志更好的方式 297
16.2 網(wǎng)絡(luò)診斷工具 297
16.3 使用Netty構(gòu)建一個在Android上運(yùn)行的Web服務(wù)器 304
16.3.1 開發(fā)背景 304
16.3.2 AndroidServer的特性 304
16.3.3 AndroidServer的設(shè)計原理 304
16.3.4 AndroidServer的使用 310
16.4 實現(xiàn)協(xié)程版本的EventBus 313
16.4.1 RxJava版本的EventBus 313
16.4.2 Kotlin Coroutine版本的EventBus 317
16.4.3 小結(jié) 322
16.5 總結(jié) 322
第17章 響應(yīng)式開發(fā)實戰(zhàn) 323
17.1 封裝一個基于RxJava的任務(wù)框架RxTask 323
17.1.1 RxTask奠基石的實現(xiàn) 324
17.1.2 利用奠基石實現(xiàn)多種Task 328
17.1.3 RxTask的改進(jìn),針對Java、Android平臺進(jìn)行適應(yīng) 335
17.2 基于Kotlin、RxJava實現(xiàn)的有限狀態(tài)機(jī) 339
17.2.1 狀態(tài)機(jī) 339
17.2.2 常用的狀態(tài)機(jī)分類 339
17.2.3 Kotlin開發(fā)的FSM 340
17.2.4 應(yīng)用 351
17.3 Kotlin、RxJava以及傳統(tǒng)的機(jī)器學(xué)習(xí)在手機(jī)質(zhì)檢上的應(yīng)用 353
17.3.1 業(yè)務(wù)背景 353
17.3.2 設(shè)計思路 353
17.3.3 代碼實現(xiàn)以及踩過的坑 355
17.3.4 后續(xù)的規(guī)劃 361
17.4 總結(jié) 361
第18章 服務(wù)端實戰(zhàn) 362
18.1 使用Ktor快速開發(fā)Web項目 362
18.1.1 Ktor介紹 362
18.1.2 Ktor服務(wù)端的使用 362
18.1.3 例子 365
18.2 使用WebFlux R2DBC開發(fā)Web項目 369
18.2.1 R2DBC介紹 369
18.2.2 R2DBC的使用 370
18.2.3 小結(jié) 376
18.3 使用NetDiscovery開發(fā)網(wǎng)絡(luò)爬蟲 376
18.3.1 NetDiscovery介紹 376
18.3.2 DSL在爬蟲框架中的使用 379
18.3.3 Kotlin Coroutines在爬蟲框架中的使用 384
18.4 實現(xiàn)智能硬件的遠(yuǎn)程控制系統(tǒng)(上) 388
18.4.1 業(yè)務(wù)背景及遠(yuǎn)程控制系統(tǒng)的功能 388
18.4.2 遠(yuǎn)程控制系統(tǒng)服務(wù)端的設(shè)計 388
18.4.3 遠(yuǎn)程控制系統(tǒng)的數(shù)據(jù)流向 389
18.4.4 遠(yuǎn)程控制系統(tǒng)服務(wù)端的相關(guān)代碼 390
18.4.5 遠(yuǎn)程控制系統(tǒng)后續(xù)的規(guī)劃 397
18.5 實現(xiàn)智能硬件的遠(yuǎn)程控制系統(tǒng)(下) 397
18.5.1 遠(yuǎn)程控制的客戶端介紹 397
18.5.2 Watcher的設(shè)計 398
18.5.3 Watcher的核心代碼 399
18.5.4 小結(jié) 408
18.6 總結(jié) 408