本書詳細介紹了Kotlin語言方方面面的特性,包括各種類型的函數,貫徹本書始終的Lambda表達式,有別于Java的委托、泛型,靈活、簡潔的DSL,常用的語法糖,相比線程更加輕量級的協程,參考RxJava實現的Flow,等等。本書還提供了大量涉及移動端、服務端甚至桌面端的案例,這些案例都是編者使用Kotlin之后的實踐和心得,同時包含很多編者封裝的library,供讀者參考、借鑒和使用。 本書適合有一定Kotlin語法基礎的讀者使用,尤其適合移動端和服務端的開發(fā)人員使用,也可以用作大專院校和培訓機構的教學參考書。
本書幾乎涵蓋了Kotlin所有的特性,包括函數特性、面向對象特性、元編程、DSL、跨平臺開發(fā)、協程、Flow、RxJava、Jetpack等,內容非常豐富。
本書還介紹了使用Kotlin開發(fā)的多個實例,如移動端實戰(zhàn)、服務端實戰(zhàn)、響應式開發(fā)實戰(zhàn)等,這些例子是對本書知識的綜合運用,對使用Kotlin進行開發(fā)的讀者具備較大的參考價值。
本書是編者系統學習Kotlin和多年實戰(zhàn)經驗的積累和總結,通過非常簡易的代碼講解Kotlin語言的各種特性,代碼實例不會涉及過于抽象的業(yè)務場景,但會通過具體代碼實例對Kotlin語言背后的設計思想和原理進行詳細分析,力圖使讀者通過實際操作快速上手和深入理解Kotlin語言的相關知識。
本書面向所有希望從事 Android 開發(fā)和服務端開發(fā)的IT從業(yè)人員,希望讀者通過閱讀本書,使用Kotlin開發(fā)應用程序的技能更上一層樓。
Kotlin是一門務實的語言。Kotlin從發(fā)展之初就受到各種語言(例如Java、C#、JavaScript、Scala、Groovy、Python等)的影響,或者說Kotlin集各家語言之長,吸收了各種語言比較好的特性。在JVM環(huán)境下,Kotlin被設計成可以和Java代碼相互操作,并可以重復使用Java現有函數庫和框架的語言。
在2016年年底,筆者工作之余,開始研究Kotlin這門語言。順便嘗試使用Kotlin編寫一些Android上的組件。
隨后,在2017-2018年,筆者負責的移動端團隊開始嘗試使用Kotlin編寫全新的App。此時恰逢谷歌宣布使用Kotlin作為Android的官方語言,這更加堅定了我們使用Kotlin的決心。個人也在此期間嘗試使用Kotlin來編寫服務端的程序。到了2019年年初,筆者跳槽到了萬物新生(當時還是愛回收)的創(chuàng)新中心。在這里,我們服務端的主力語言就是Kotlin。使用Kotlin編寫后端服務在當時甚至到現在都是一件比較酷的事情。
這些年來,筆者在兩家公司使用Kotlin做了很多項目,從App到桌面程序再到服務端程序,積累了很多相關的編程經驗。因此編寫了本書,希望通過本書能讓讀者了解這門務實的語言,以及嘗試使用這門語言。Kotlin也是基于JVM的語言,上手不難,但是其思想跟Java大相徑庭。
每隔幾年,我們都會聽到一種聲音xxx語言將會取代Java,取代Java的語言也從之前的C#、PHP、Python變成了Go、Kotlin。其實,只要從TIOBE的榜單就可以看到,這些年來Java 一直占據著這份榜單前三的位置,甚至很多年來都是。Java龐大的生態(tài)系統、海量的項目決定了其在未來很多年內不可能被取代。
題外話,在下一代的Java虛擬機Graal VM中,除了支持基于JVM的語言Java、Scala、Groovy、Kotlin等外,還支持JavaScript、Python、Ruby、R,以及基于LLVM的C、C 、Rust。Graal VM會讓Java變得更加強大。
Kotlin的出現是為了編寫更好的Java,Kotlin可以與Java進行互操作,并且Kotlin有自己獨特的優(yōu)勢:
? 豐富的語法糖
? 強類型
? 函數式編程
? 協程
……
因此,Kotlin也被戲稱為Java好的第三方庫。
本書詳細介紹了Kotlin語言的各種特性,例如花了大量篇幅介紹各種類型的函數,貫徹本書始終的Lambda表達式,有別于Java的委托、泛型,靈活、簡潔的DSL,常用的語法糖,相比線程更加輕量級的協程,參考RxJava實現的Flow,等等。
本書不僅介紹Kotlin的功能,還會對部分Kotlin特性進行源碼解析,也會對各個特性進行深入的總結。
另外,本書帶來了豐富的案例,涉及移動端、服務端甚至桌面端。它們都是筆者在大量使用 Kotlin之后的實踐和心得,同時包含很多筆者封裝的library,供讀者參考、借鑒和使用。因此,本書主要面向移動端、服務端的讀者。
本書編寫的時間跨度有一點長,歷經了Kotlin 1.3到當前的Kotlin 1.5,F在Kotlin已經變成筆者的主力編程語言。當然,Kotlin的研發(fā)團隊也在不斷更新,據說每隔6個月會發(fā)布一個新版本,有點類似Java發(fā)布新版本的節(jié)奏。筆者也會不斷跟進Kotlin新版本的特性。
總之,本書盡量多地介紹Kotlin方方面面的特性,用豐富的例子來增強說服力。本書共18章,其中第10、13、14、15(部分內容)、17(部分內容)章是由易龐宙編寫的,其余是由沈哲編寫的。本書的資源在GitHub中,地址為https://github.com/fengzhizi715/Advance-Kotlin-Tutorials。
當然,在編寫本書的過程中,Kotlin也在不斷地更新、完善。另外,筆者才疏學淺,書中難免會有不當之處,歡迎讀者批評指正,一起討論Kotlin的方方面面。
后,寫書是一個枯燥、漫長且耗費大量時間、精力的事情,感謝清華大學出版社的編輯、我的同事、家人對我的幫助,特別是我的太太一直在我身后默默地為家庭付出。
沈 哲
2021年6月
沈 哲,現就職于萬物新生(愛回收),擔任創(chuàng)新中心技術總監(jiān),負責AIoT 產品相關的研發(fā)工作。具有多年的服務端、移動端研發(fā)經驗,熟悉函數響應式編程,對計算機視覺有一定的研究。曾負責過一款移動端深度鏈接的產品,日活數千萬,該產品已于2019年初以千萬級別的交易額賣給極光,后更名為極光魔鏈。出版著作《RxJava 2.x 實戰(zhàn)》。
易龐宙,Android開源愛好者,RxTask庫、全面屏適配庫以及一些Android常用開源工具的開發(fā)者,CSDN博主。負責過搜床科技集團Android開發(fā),例如xbed、酒店自助入住App開發(fā)等,目前就職于廣州極飛科技股份有限公司,擔任高級Android開發(fā)工程師。
第1章 認識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 總結 3
第2章 Kotlin的函數與類 4
2.1 函數的基本概念 4
2.1.1 函數的參數 5
2.1.2 函數 8
2.2 Kotlin的類(一) 11
2.2.1 構造函數和初始化塊 12
2.2.2 屬性 15
2.2.3 抽象類 16
2.2.4 嵌套類和內部類 16
2.2.5 枚舉類 17
2.3 Kotlin的類(二) 18
2.3.1 對象聲明和對象表達式 18
2.3.2 伴生對象 19
2.3.3 數據類 20
2.3.4 密封類 23
2.4 總結 24
第3章 Kotlin的函數式編程 25
3.1 函數式編程與高階函數 25
3.1.1 函數式編程 25
3.1.2 高階函數 25
3.2 Lambda表達式 29
3.2.1 Java 8的Lambda 29
3.2.2 Kotlin的Lambda語法 31
3.2.3 簡化Kotlin的Lambda表達式 31
3.2.4 方法引用 32
3.2.5 Kotlin支持SAM轉換 33
3.2.6 使用高階函數的例子 34
3.2.7 換個角度看 Lambda表達式 35
3.3 集合、序列和Java中的流 38
3.3.1 集合中的函數式API 38
3.3.2 序列和流 41
3.4 總結 41
第4章 內聯函數與擴展函數 42
4.1 內聯函數 42
4.1.1 inline的使用 42
4.1.2 禁用內聯noinline 45
4.1.3 非局部返回以及crossinline的使用 47
4.2 內聯屬性 48
4.2.1 內聯屬性 48
4.2.2 內聯類 48
4.3 擴展函數 48
4.3.1 擴展函數的特性 48
4.3.2 常用標準庫的擴展函數 51
4.4 擴展屬性 56
4.5 總結 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 總結 73
第6章 泛型 74
6.1 類型擦除 74
6.1.1 Java泛型的優(yōu)點 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 泛型的應用 85
6.4 總結 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 構造函數引用,獲取類的構造函數 91
7.3.3 函數引用,獲取類的成員函數 92
7.3.4 屬性引用,獲取類的成員變量 94
7.4 Java反射和Kotlin反射(下) 96
7.4.1 獲取類的其他信息 96
7.4.2 Java反射與Kotlin反射的互操作性 98
7.5 總結 99
第8章 DSL的構建 100
8.1 DSL介紹 100
8.2 構建一個DSL的多種方式 101
8.2.1 帶接收者的函數類型 101
8.2.2 帶接收者的Lambda 101
8.2.3 創(chuàng)建一個自己的DSL 102
8.2.4 將擴展函數改成DSL的方式 104
8.2.5 使用運算符重載實現DSL 105
8.2.6 使用中綴表達式實現DSL 106
8.2.7 Kotlin DSL的實際使用封裝路由框架的使用 107
8.3 總結 108
第9章 常用語法糖與設計模式 110
9.1 運算符重載 110
9.2 中綴表達式 112
9.2.1 在擴展函數中使用中綴表達式 113
9.2.2 在成員函數中使用中綴表達式 113
9.3 作用域函數 114
9.3.1 作用域函數的概念 114
9.3.2 如何優(yōu)雅地使用作用域函數 114
9.4 Contract契約 118
9.4.1 Contract的概念 119
9.4.2 Contract的特性 119
9.4.3 Contract源碼解析 120
9.4.4 小結 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 更好地使用設計模式 126
9.6.1 單例模式 126
9.6.2 builder模式 127
9.6.3 觀察者模式 128
9.6.4 狀態(tài)模式 129
9.7 總結 130
第10章 跨平臺開發(fā) 131
10.1 跨平臺的簡單介紹 131
10.1.1 跨平臺開發(fā)的愿景 131
10.1.2 跨平臺開發(fā)當前的主流技術 131
10.1.3 Kotlin與Flutter的對比 132
10.2 利用Ktor-Client實現跨平臺網絡請求 132
10.2.1 什么是Ktor 132
10.2.2 Ktor-Client的使用 132
10.3 總結 142
第11章 協程及其應用 143
11.1 協程的基本概念 143
11.1.1 協程的定義 143
11.1.2 為何要使用協程 143
11.1.3 Kotlin協程的基本概念 148
11.2 Coroutine builders 149
11.2.1 launch和async 149
11.2.2 runBlocking 152
11.3 掛起函數 152
11.3.1 delay 152
11.3.2 yield 153
11.3.3 withContext 154
11.3.4 coroutineScope 156
11.4 協程的上下文和調度 156
11.4.1 協程的調度 156
11.4.2 父子協程 158
11.4.3 多個CoroutineContext進行 操作 160
11.4.4 CoroutineContext Job 161
11.5 協程的作用域 CoroutineScope 162
11.5.1 盡量少用GlobalScope 162
11.5.2 安全地使用CoroutineScope 163
11.5.3 在Android中更好地使用Coroutines 163
11.6 Channel機制 164
11.6.1 生產者和消費者 164
11.6.2 管道 165
11.6.3 channel緩沖 167
11.6.4 actor 168
11.6.5 Select表達式 169
11.7 總結 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實現并發(fā)操作 186
12.4.4 并行操作 188
12.5 Flow其他的操作符 189
12.5.1 轉換操作符 189
12.5.2 限制大小的操作符 189
12.5.3 終端操作符 189
12.5.4 合并操作符 190
12.5.5 扁平化操作符 193
12.6 總結 195
第13章 RxJava的新特性及常用操作符 198
13.1 RxJava入門 198
13.1.1 RxJava入門理念 198
13.1.2 RxJava的基礎知識 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 轉換操作符 215
13.3.3 過濾操作符 220
13.4 總結 227
第14章 RxJava的核心機制 229
14.1 ObservableSource、Observable、Observer的同流合污 229
14.2 恐怖的Function機制 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 總結 243
第15章 Jetpack 244
15.1 Jetpack介紹 244
15.1.1 客戶端的架構迭代 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結合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實現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 小結 275
15.6 Navigation用法詳解 276
15.6.1 Navigation的配置 276
15.6.2 Navigation的基本使用 277
15.6.3 Navigation原理解析 284
15.6.4 小結 287
15.7 總結 287
第16章 Android實戰(zhàn) 288
16.1 構建一個日志框架 288
16.1.1 Android日志框架L 288
16.1.2 如何開發(fā)一款類似L的日志框架 289
16.1.3 記錄Android日志更好的方式 297
16.2 網絡診斷工具 297
16.3 使用Netty構建一個在Android上運行的Web服務器 304
16.3.1 開發(fā)背景 304
16.3.2 AndroidServer的特性 304
16.3.3 AndroidServer的設計原理 304
16.3.4 AndroidServer的使用 310
16.4 實現協程版本的EventBus 313
16.4.1 RxJava版本的EventBus 313
16.4.2 Kotlin Coroutine版本的EventBus 317
16.4.3 小結 322
16.5 總結 322
第17章 響應式開發(fā)實戰(zhàn) 323
17.1 封裝一個基于RxJava的任務框架RxTask 323
17.1.1 RxTask奠基石的實現 324
17.1.2 利用奠基石實現多種Task 328
17.1.3 RxTask的改進,針對Java、Android平臺進行適應 335
17.2 基于Kotlin、RxJava實現的有限狀態(tài)機 339
17.2.1 狀態(tài)機 339
17.2.2 常用的狀態(tài)機分類 339
17.2.3 Kotlin開發(fā)的FSM 340
17.2.4 應用 351
17.3 Kotlin、RxJava以及傳統的機器學習在手機質檢上的應用 353
17.3.1 業(yè)務背景 353
17.3.2 設計思路 353
17.3.3 代碼實現以及踩過的坑 355
17.3.4 后續(xù)的規(guī)劃 361
17.4 總結 361
第18章 服務端實戰(zhàn) 362
18.1 使用Ktor快速開發(fā)Web項目 362
18.1.1 Ktor介紹 362
18.1.2 Ktor服務端的使用 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 小結 376
18.3 使用NetDiscovery開發(fā)網絡爬蟲 376
18.3.1 NetDiscovery介紹 376
18.3.2 DSL在爬蟲框架中的使用 379
18.3.3 Kotlin Coroutines在爬蟲框架中的使用 384
18.4 實現智能硬件的遠程控制系統(上) 388
18.4.1 業(yè)務背景及遠程控制系統的功能 388
18.4.2 遠程控制系統服務端的設計 388
18.4.3 遠程控制系統的數據流向 389
18.4.4 遠程控制系統服務端的相關代碼 390
18.4.5 遠程控制系統后續(xù)的規(guī)劃 397
18.5 實現智能硬件的遠程控制系統(下) 397
18.5.1 遠程控制的客戶端介紹 397
18.5.2 Watcher的設計 398
18.5.3 Watcher的核心代碼 399
18.5.4 小結 408
18.6 總結 408