內容提要
《Android高級進階》是Android的進階學習指南,主要為Android國中級開發者進階所需的知識,高級開發者也可以從本書中發現很多共鳴點。《Android高級進階》從8個方面對50個知識點進行分類講解,包括基礎篇、系統架構篇、經驗總結篇、新技術篇、性能最佳化篇、移動安全篇、工具篇、測試篇。熟練掌握這些知識點後,應該就能夠應付實際項目開發中的絕大部分問題了。
《Android高級進階》的主要目的在於給讀者一個完整的Android中高級開發者知識圖譜。筆者希望通過《Android高級進階》的系統講解,能夠幫助讀者在面試和工作中收穫自己滿意的成績。
圖書目錄
第1篇 基礎篇
第1章 Android觸摸事件傳遞機制 2
1.1 觸摸事件的類型 2
1.2 事件傳遞的三個階段 3
1.3 View的事件傳遞機制 4
1.4 ViewGroup的事件傳遞機制 10
第2章 Android View的繪製流程16
2.1 繪製的整體流程 17
2.2 MeasureSpec17
2.3 Measure19
2.4 Layout22
2.5 Draw22
第3章 Android 動畫機制25
3.1 逐幀動畫(Frame Animation) 25
3.1.1 XML 資源檔案方式25
3.1.2 代碼方式26
3.2 補間動畫(Tween Animation) 27
3.2.1 插值器Interpolator 27
3.2.2 AlphaAnimation 29
3.2.3 ScaleAnimation 30
3.2.4 TranslateAnimation 31
3.2.5 RotateAnimation 32
3.2.6 自定義補間動畫34
3.3 屬性動畫(Property Animation) 34
3.3.1 Evaluator 35
3.3.2 AnimatorSet 36
3.3.3 ValueAnimator 36
3.3.4 ObjectAnimator 38
3.4 過渡動畫(Transition Animation) 40
第4章 Support Annotation Library 使用詳解46
4.1 Nullness 註解 47
4.2 資源類型註解 48
4.3 類型定義註解 50
4.4 執行緒註解 52
4.5 RGB 顏色值註解 52
4.6 值範圍註解 53
4.7 許可權註解 53
4.8 重寫函式註解 54
4.9 返回值註解 55
4.10 @VisibleForTesting55
4.11 @Keep55
第5章 Percent Support Library使用詳解57
第6章 Design Support Library使用詳解62
6.1 Snackbar62
6.2 TextInputLayout63
6.3 TabLayout64
6.4 NavigationView65
6.4.1 導航選單66
6.4.2 導航頭部67
6.5 FloatingActionButton70
6.5.1 使用浮動操作按鈕70
6.5.2 其他選項71
6.5.3 點擊事件71
6.6 CoordinatorLayout72
6.7 CollapsingToolbarLayout73
6.8 BottomSheetBehavior75
第7章 Android Studio中的NDK開發77
7.1 ABI的基本概念 77
7.2 引入預編譯的二進制C/C++ 函式館 79
7.3 直接從C/C++ 源碼編譯 79
7.3.1 配置ndk.dir 變數79
7.3.2 在Gradle 中配置NDK 模組79
7.3.3 添加C/C++ 檔案到指定的目錄81
7.4 使用.so 檔案的注意事項 81
7.4.1 使用高平台版本編譯的.so 檔案運行在低版本的設備上81
7.4.2 混合使用不同的C++ 運行時編譯的.so 檔案82
7.4.3 沒有為每個支持的CPU 架構提供對應的.so 檔案82
7.4.4 將.so 檔案放在錯誤的地方82
7.4.5 只提供armeabi 架構的.so 檔案而忽略其他ABIs 的83
第8章 Gradle 必知必會85
8.1 共享變數的定義 85
8.2 通用配置 87
8.3 aar 函式館的引用 88
8.4 簽名和混淆的配置 90
第9章 通過Gradle打包發布函式館到JCenter和Maven Central 92
9.1 Maven Central 和JCenter92
9.1.1 Maven Central 93
9.1.2 JCenter 93
9.2 Android Studio 獲取函式館的原理 94
9.3 上傳函式館到JCenter96
9.3.1 步驟一:在Bintray 網站上註冊一個賬號96
9.3.2 步驟二:創建一個Sonatype 賬號96
9.3.3 步驟三:在Bintray 網站使能自動簽名97
9.3.4 步驟四:生成POM 相關的信息100
9.3.5 步驟五:上傳函式館到Bintray 104
9.3.6 步驟六:發布Bintray 用戶倉庫到JCenter 107
9.3.7 步驟七:同步函式館到Maven Central 109
第10章 Builder模式詳解110
10.1 經典的Builder 模式 110
10.2 Builder 模式的變種 113
10.3 變種Builder 模式的自動化生成 119
10.4 開源函式館的例子 122
第11章 註解在Android 中的套用124
11.1 註解的定義 124
11.2 標準註解 125
11.2.1 編譯相關註解125
11.2.2 資源相關註解125
11.2.3 元註解125
11.3 運行時註解 127
11.4 編譯時註解 127
11.4.1 定義註解處理器127
11.4.2 註冊註解處理器131
11.4.3 android-apt外掛程式132
第12章 ANR產生的原因及其定位分析134
12.1 ANR 產生的原因 135
12.2 典型的ANR 問題場景 135
12.3 ANR 的定位和分析 136
12.3.1 Logcat 日誌信息136
12.3.2 traces.txt 日誌信息138
12.4 ANR的避免和檢測 141
12.4.1 StrictMode141
12.4.2 BlockCanary 142
第13章 Android異步處理技術144
13.1 Thread144
13.2 HandlerThread146
13.3 AsyncQueryHandler149
13.4 IntentService150
13.5 Executor Framework153
13.6 AsyncTask155
13.7 Loader156
13.8 總結 159
第14章 Android數據序列化方案研究160
14.1 Serializable160
14.2 Parcelable166
14.3 SQLiteDatabase169
14.4 SharedPreferences170
14.5 JSON171
14.6 Protocol Buffers及Nano-Proto-Buffers171
14.7 FlatBuffers171
第15章 Android WebView Java 和JavaScript 互動詳解173
15.1 Java 調用JavaScript173
15.2 JavaScript 調用Java174
第2篇 系統架構篇
第16章 MVP模式及其在Android中的實踐180
16.1 MVP 的基本概念 180
16.2 MVP 與MVC 的區別 181
16.3 MVP 的開源實現 182
16.3.1 Android-Architecture 182
16.3.2 TODO-MVP 182
16.3.3 TODO-MVP-Loaders 183
16.3.4 TODO-MVP-Clean 183
16.3.5 TODO-Databinding 184
16.3.6 其他開源參考實現184
16.4 MVP 的好處 185
16.5 MVP 存在的問題 185
第17章 MVVM模式及Android DataBinding實戰186
17.1 Data Binding 表達式 187
17.2 數據對象 188
17.3 數據綁定 188
17.4 事件綁定 189
第18章 觀察者模式的拓展:事件匯流排191
18.1 為何要使用 191
18.2 原理 192
18.3 開源實現 193
18.3.1 EventBus 193
18.3.2 otto 194
18.4 與觀察者模式及Android 廣播的區別 196
第19章 書寫簡潔規範的代碼197
19.1 Java 編碼規範 197
19.1.1 原始碼檔案的定義197
19.1.2 原始碼檔案的結構197
19.1.3 遵循的格式198
19.1.4 命名約定200
19.1.5 Javadoc 200
19.2 Android 命名規範 200
19.2.1 布局檔案的命名200
19.2.2 資源檔案的命名201
19.2.3 類的命名201
19.3 CheckStyle 的使用 202
第20章 基於開源項目搭建屬於自己的技術堆疊203
20.1 APP 的整體架構 203
20.2 技術選型的考量點 205
20.3 日誌記錄能力 205
20.4 JSON 解析能力 207
20.4.1 gson 207
20.4.2 jackson 207
20.4.3 Fastjson 208
20.4.4 LoganSquare 208
20.5 資料庫操作能力 210
20.5.1 ActiveAndroid 210
20.5.2 ormlite 211
20.5.3 greenDAO 211
20.5.4 Realm 212
20.6 網路通信能力 213
20.6.1 android-async-http 213
20.6.2 OkHttp 215
20.6.3 Volley 216
20.6.4 Retrofit 217
20.7 圖片快取和顯示能力 217
20.7.1 BitmapFun 218
20.7.2 Picasso 218
20.7.3 Glide 218
20.7.4 Fresco 219
20.7.5 Android-Universal-Image-Loader 219
第3篇 經驗總結篇
第21章 64K方法數限制原理與解決方案222
21.1 64K 限制的原因 222
21.2 使用MultiDex 解決64K 限制的問題 223
21.2.1 Android 5.0 之前的版本223
21.2.2 Android 5.0 及之後的版本223
21.3 如何避免出現64K 限制 223
21.4 配置MultiDex224
21.5 MultiDex Support Library 的局限性 226
21.6 在開發階段最佳化MultiDex 的構建 227
第22章 Android 外掛程式框架機制研究與實踐230
22.1 基本概念 231
22.1.1 宿主和外掛程式231
22.1.2 ClassLoader 機制231
22.2 開源框架 231
22.2.1 android-pluginmgr 232
22.2.2 dynamic-load-apk 232
22.2.3 DynamicAPK 232
22.2.4 DroidPlugin 233
22.2.5 Small 234
第23章 推送機制實現原理詳解235
23.1 推送的開源實現方案 236
23.1.1 基於XMPP 協定236
23.1.2 基於MQTT 協定236
23.2 推送的第三方平台 236
23.3 自己實現推送功能 237
23.3.1 長連線的建立(TCPConnectThread)237
23.3.2 數據的傳送(TCPSendThread)237
23.3.3 數據的接收(TCPReceiveThread)238
23.3.4 心跳包的實現(TCPHeartBeatThread)240
第24章 APP 瘦身經驗總結241
24.1 APP 為什麼變胖了 241
24.2 從APK 檔案的結構說起 242
24.3 最佳化圖片資源占用的空間 245
24.3.1 無損壓縮[ImageOptim] 246
24.3.2 有損壓縮[ImageAlpha] 246
24.3.3 有損壓縮[TinyPNG] 246
24.3.4 PNG/JPEG 轉換為WebP246
24.3.5 儘量使用NinePatch 格式的PNG 圖247
24.4 使用Lint 刪除無用資源 248
24.5 利用Android Gradle 配置 248
24.5.1 minifyEnable248
24.5.2 shrinkResources 249
24.5.3 resConfigs 249
24.5.4 ndk.abiFilters 250
24.6 重構和最佳化代碼 250
24.7 資源混淆 251
24.8 外掛程式化 251
第25章 Android Crash 日誌收集原理與實踐252
25.1 Java 層Crash 捕獲機制 253
25.1.1 基本原理253
25.1.2 執行緒信息254
25.1.3 SharedPreference 信息255
25.1.4 系統設定257
21.1.5 Logcat 中的日誌記錄261
25.1.6 自定義Log 檔案中的內容264
25.1.7 MemInfo 信息266
25.2 Native 層Crash 捕獲機制 267
25.3 Crash 的上報 269
第4篇 新技術篇
第26章 函式式編程思想及其在Android中的套用272
26.1 代碼的簡化 274
26.2 Operators 簡介 275
第27章 依賴注入及其在Android中的套用277
27.1 基本概念 277
27.1.1 構造函式注入278
27.1.2 Setter 函式注入279
27.1.3 接口注入279
27.2 為何需要框架 280
27.3 開源框架的選擇 280
27.3.1 ButterKnife 280
27.3.2 RoboGuice 282
27.3.3 Dagger 285
27.3.4 Dagger2 288
27.3.5 框架的對比289
第28章 Android世界的Swift:Kotlin在Android中的套用290
28.1 選擇Kotlin 的原因 290
28.2 Kotlin 的安裝和配置 291
28.3 Kotlin 語言的特性 292
28.3.1 可表達性292
28.3.2 空類型安全294
28.3.3 擴展函式295
28.4 Kotlin 的Gradle 配置 296
28.5 將Java 類轉換成Kotlin 類 299
28.6 相關資料 302
第29章 React Native For Android入門指南304
29.1 環境配置 304
29.1.1 Homebrew 304
29.1.2 nvm 305
29.1.3 Node.js 305
29.1.4 watchman 306
29.1.5 flow 306
29.2 Android 開發環境的要求 306
29.3 React Native 工程配置 307
29.3.1 安裝react-native 307
29.3.2 生成工程307
29.4 Android Studio 工程概覽 308
29.5 React Native 依賴庫修改為本地 314
29.5.1 下載react-native.aar 314
29.5.2 react-native.aar 的檔案內容315
29.5.3 Gradle 本地依賴316
29.5.4 將node_modules 上傳到svn/git 318
29.6 React Native 學習建議 319
第30章 Android線上熱修複方案研究320
30.1 線上熱修復的基本流程 320
30.2 Dexposed321
30.2.1 如何集成322
30.2.2 基本用法323
30.2.3 線上熱修復325
30.2.4 平台的限制328
30.3 AndFix329
30.3.1 如何集成329
30.3.2 補丁包生成工具331
30.3.3 平台的限制332
30.4 Nuwa332
30.4.1 基本原理332
30.4.2 如何集成333
30.4.3 補丁生成工具334
30.4.4 平台的限制334
30.5 總結 334
第31章 面向切面編程及其在Android中的套用335
31.1 AOP 的基本概念 335
31.2 代碼織入的時機 336
31.3 基於AspectJ 實現Android 平台的AOP337
31.3.1 Hugo 的用法簡介337
31.3.2 Hugo 的實現原理339
31.4 其他AOP 開源框架 344
第32章 基於Facebook Buck改造Android構建系統345
32.1 Buck環境配置 346
32.1.1 Homebrew 方式346
32.1.2 手動構建方式346
32.1.3 安裝Watchman 348
32.1.4 安裝Android SDK 和Android NDK 348
32.2 快速創建基於Buck 構建的Android 工程 349
32.3 Buck 的基本概念 351
32.3.1 構建規則(Build Rule)352
32.3.2 構建目標(Build Target)354
32.3.3 構建檔案(Build File)355
32.3.4 構建目標模式(Build Target Pattern)356
32.4 項目改造實戰 357
32.4.1 步驟一:手動下載工程依賴的第三方Jar包或者aar包357
32.4.2 步驟二:將R.* 常量修改為非final 的357
32.4.3 步驟三:創建BUCK 檔案358
32.4.4 步驟四:編譯Buck 的buck-android-support 363
32.4.5 步驟五:Exopackage 的使用363
32.5 Buck 的自動化改造 366
第5篇 性能最佳化篇
第33章 代碼最佳化368
33.1 數據結構的選擇 368
33.2 Handler 和內部類的正確用法 370
33.3 正確地使用Context373
33.3.1 Context 的種類374
33.3.2 錯誤使用Context 導致的記憶體泄漏374
33.3.3 不同Context 的對比376
33.4 掌握Java 的四種引用方式 376
33.5 其他代碼微最佳化 377
33.5.1 避免創建非必要的對象377
33.5.2 對常量使用static final 修飾378
33.5.3 避免內部的Getters/Setters 378
33.5.4 代碼的重構378
第34章 圖片最佳化379
34.1 圖片的格式 379
34.1.1 JPEG 380
34.1.2 PNG 380
34.1.3 GIF 380
34.1.4 WebP 380
34.2 圖片的壓縮 380
34.2.1 無損壓縮ImageOptim 381
34.2.2 有損壓縮ImageAlpha 381
34.2.3 有損壓縮TinyPNG 381
34.2.4 PNG/JPEG 轉換為WebP381
34.2.5 儘量使用NinePatch 格式的PNG 圖382
34.3 圖片的快取 382
第35章 電量最佳化383
35.1 BroadcastReceiver383
35.2 數據傳輸 384
35.3 位置服務 384
35.4 AlarmManager386
35.5 WakeLock386
第36章 布局最佳化388
36.1 include 標籤共享布局 388
36.2 ViewStub 標籤實現延遲載入 389
36.3 merge 標籤減少布局層次 391
36.4 儘量使用CompoundDrawable392
36.5 使用Lint393
第37章 網路最佳化395
37.1 避免DNS 解析 395
37.2 合併網路請求 395
37.3 預先獲取數據 396
37.4 避免輪詢 396
37.5 最佳化重連機制 396
37.6 離線快取 396
37.7 壓縮數據大小 396
37.8 不同的網路環境使用不同的逾時策略 397
37.9 CDN 的使用 397
第6篇 移動安全篇
第38章 Android混淆機制詳解400
38.1 Java 代碼的混淆 400
38.1.1 Proguard 的特性401
38.1.2 Proguard 的使能和配置401
38.1.3 proguard-rules.pro 檔案的編寫404
38.1.4 Proguard 生成的檔案407
38.1.5 Proguard 混淆規則匯總409
38.2 Native(C/C++)代碼的混淆 409
38.3 資源檔案的混淆 409
第39章 Android 反編譯機制詳解411
39.1 資源檔案的反編譯 411
39.1.1 ApkTool 的安裝411
39.1.2 ApkTool 的使用412
39.2 Java 代碼的反編譯 413
第40章 客戶端敏感信息隱藏技術研究414
40.1 敏感信息嵌套在strings.xml 中 415
40.2 敏感信息隱藏在Java 原始碼中 415
40.3 敏感信息隱藏在BuildConfig 中 417
40.4 使用DexGuard418
40.5 對敏感信息進行偽裝或者加密 419
40.6 敏感信息隱藏在原生函式館中(.so檔案) 419
40.7 對APK進行加固處理 419
第41章 Android 加固技術研究421
41.1 愛加密的主要功能 421
41.1.1 漏洞分析421
41.1.2 加密服務422
41.1.3 渠道監測423
41.2 常見APP 漏洞及風險 423
41.2.1 靜態破解423
41.2.2 二次打包424
41.2.3 本地儲存數據竊取424
41.2.4 界面截取424
41.2.5 輸入法攻擊424
41.2.6 協定抓取424
41.3 Android 程式反破解技術 424
41.3.1 對抗反編譯424
41.3.2 對抗靜態分析425
41.3.3 對抗動態調試425
41.3.4 防止重編譯425
41.4 加固技術研究知識儲備 426
41.4.1 掌握常見的破解分析工具426
41.4.2 掌握Dalvik 指令集代碼428
41.4.3 掌握Dex 和Odex 檔案格式428
41.4.4 掌握Smali 檔案格式428
41.4.5 掌握基於Android 的ARM 彙編語言基礎428
第42章 Android安全編碼429
42.1 WebView 遠程代碼執行 429
42.2 WebView 密碼明文保存 430
42.3 Android 本地拒絕服務 431
42.3.1 非法序列化對象導致的ClassNotFoundException 431
42.3.2 空Action 導致的NullPointerException 432
42.3.3 強制類型轉換導致的ClassCastException 433
42.3.4 數組越界導致的IndexOutOfBoundsException 433
42.4 SharedPreference 全局任意讀寫 434
42.5 密鑰硬編碼 434
42.6 AES/DES/RSA 弱加密 434
42.7 隨機函式使用錯誤 437
42.8 WebView 忽略SSL 證書 438
42.9 HTTPS 證書弱校驗 438
42.9.1 自定義X509TrustManager 未實現安全校驗438
42.9.2 自定義HostnameVerifier 默認接受所有域名441
42.9.3 SSLSocketFactory 信任所有證書442
42.10 PendingIntent 使用不當 443
第7篇 工具篇
第43章 Android調試工具Facebook Stetho 446
43.1 視圖布局監視 447
43.2 資料庫監視 447
43.3 網路監視 448
43.3.1 網路模組使用的是HTTPUrlConnection 449
43.3.2 網路模組使用的是OkHttp 452
43.4 dumpapp454
43.4.1 外掛程式的編寫454
43.4.2 外掛程式的集成456
43.4.3 外掛程式的使用456
43.5 Javascript 控制台 457
43.6 最佳實踐 457
第44章 記憶體泄漏檢測函式館LeakCanary 460
44.1 基本概念 461
44.2 LeakCanary 的集成 461
44.3 LeakCanary 的原理 465
44.4 LeakCanary 的定製 469
44.4.1 RefWatcher 的自定義469
44.4.2 通知頁面樣式的自定義470
44.4.3 記憶體泄漏堆疊信息保存個數的自定義471
44.4.4 Watcher 的延時471
44.4.5 自定義記憶體泄漏堆疊信息和heap dump 的處理方式471
44.4.6 忽略特定的弱引用472
44.4.7 不監視特定的Activity 類472
第45章 基於Facebook Redex實現Android APK的壓縮和最佳化474
45.1 轉換的時機 474
45.2 管道的思想 475
45.3 減少位元組碼的意義 475
45.4 混淆和壓縮 475
45.5 使用內聯函式 476
45.6 無用代碼的消除 477
45.7 Redex 的集成和使用 478
45.7.1 依賴的安裝478
45.7.2 下載,構建和安裝478
45.7.3 使用478
第46章 Android Studio你所需要知道的功能479
46.1 Annotate479
46.2 .ignore 外掛程式 480
46.3 Live Templates481
46.4 集成Bug 管理系統 482
第8篇 測試篇
第47章 Android單元測試框架簡介486
47.1 Java 單元測試框架JUnit486
47.2 Android 單元測試框架Robolectric 3.0488
47.3 Java 模擬測試框架Mockito490
47.3.1 行為的驗證490
47.3.2 Stub(樁函式)的使用491
第48章 Android UI自動化測試框架簡介492
48.1 Monkey492
48.2 MonkeyRunner493
48.3 UIAutomator493
48.4 Robotium494
48.5 Espresso494
48.6 Appium494
第49章 Android靜態代碼分析實戰495
49.1 Java代碼規範檢查工具CheckStyle495
49.1.1 Gradle方式495
49.1.2 Android Studio外掛程式方式497
49.2 Java靜態代碼分析工具FindBugs498
49.2.1 Gradle方式498
49.2.2 Android Studio外掛程式方式499
49.3 Java靜態代碼分析工具PMD500
49.3.1 Gradle方式500
49.3.2 Android Studio外掛程式方式501
49.4 Android代碼最佳化工具Lint501
49.4.1 Gradle方式501
49.4.2 Android Studio外掛程式方式502
第50章 基於Jenkins+Gradle搭建Android持續集成編譯環境503
50.1 Tomcat的下載和啟動 503
50.2 Jenkins的下載和運行 505
50.3 Jenkins外掛程式的安裝 506
50.4 Jenkins全局配置 507
50.4.1 配置JDK 環境507
50.4.2 配置Android SDK 環境507
50.4.3 配置Git 環境508
50.4.4 配置SVN 環境508
50.4.5 配置Gradle 環境508
50.5 JOB相關的操作 508
50.5.1 JOB 的創建508
50.5.2 JOB 的配置509
50.5.3 Gradle 的配置510
50.5.4 構建觸發器的配置511
50.5.5 參數化構建514
50.6 Jenkins預定義的環境變數 514