Android工程化最佳實踐 ( 簡體 字) |
作者:金凱 | 類別:1. -> 程式設計 -> 手機程式 -> Android |
譯者: |
出版社:電子工業出版社 | 3dWoo書號: 50879 詢問書籍請說出此書號!【有庫存】 NT售價: 445 元 |
出版日:3/1/2019 |
頁數:400 |
光碟數:0 |
|
站長推薦: |
印刷:黑白印刷 | 語系: ( 簡體 版 ) |
|
加入購物車 │加到我的最愛 (請先登入會員) |
ISBN:9787121359248 |
作者序 | 譯者序 | 前言 | 內容簡介 | 目錄 | 序 |
(簡體書上所述之下載連結耗時費功, 恕不適用在台灣, 若讀者需要請自行嘗試, 恕不保證) |
作者序: |
譯者序: |
前言:開發者的焦慮 當今,Android和iOS手機無論在系統還是外形上都趨于雷同,App功能的差異也是微乎其微,移動端發展趨于緩慢已成為開發者的共識。移動開發者面對小程序、React Native、Flutter和Weex跨平臺方案都顯得焦躁不安,對于自己未來需要發展和生根的方向或多或少地會感到迷茫。 從市場的角度來說,公司缺少的并非基礎的開發人員,更希望可以招聘到有大量實踐經驗的開發者。要進階成為高級開發者,更需要閱讀有深度、偏重實踐的書籍。因此,我從2015年8月開始在GitHub上創建了“Android-Best-Practices”項目。這個項目的目的是將經實際驗證的經驗分享出來,力求達到“學完即用”的效果。在收到出版社的邀請后,我將相關的文章進行重寫,同時新增大量內容,目的是讓更多的開發者可以在短時間內得到更多的實際經驗。 面對當前移動開發的生存環境,開發者的無力感會越發嚴重。作為移動應用開發者,應該了解與本職工作相關的知識,同時多涉獵其他鄰域。如果你想快速鞏固移動開發的知識后再投身到大前端中去,那么這本書很適合你。當閱讀完本書的每一章后,你收獲的是已經經過時間檢驗的知識,需要做的僅僅是去實踐它、理解它。 寫作風格 本書不會像其他書籍一樣提供完整的代碼下載,也不會花大量的篇幅分析源碼。官方每隔幾個月就會對源碼的實現進行各種修改,而源碼的設計思路則較為穩定。“授人以魚不如授人以漁”,本書會將分析源碼的過程提煉出來,主要闡述設計思路和關鍵的代碼,甚至會為了可讀性刪除沒必要的代碼邏輯。這樣做的目的是希望讀者既可以快速理解源碼的思路,又不會陷入代碼的困境中。 本書內容 本書分為基礎知識和工程優化兩部分。基礎知識部分講述基礎知識,讀者可以找到合適的第三方庫來提高業務開發速度;工程優化部分講述工程實踐方面的內容,仔細閱讀此部分,可以提升自身內在的知識廣度。 基礎知識 在實際工程中,Android本身的API大多不會被直接使用,需要做二次封裝和擴展。基礎知識部分將基礎的知識提升到一個實踐的層面,不再講述如何使用它們,而是講如何通過封裝這些API解決實際中的各種問題。 第1章 Java的反射是必知必會的內容,我們需要知道: ? 什么時候該用反射,Android中的反射和JDK中的反射有何不同? ? 反射低效的原因是什么,如何讓其變得高效。反射的緩存該如何實現? ? 為什么Android P不讓反射被@hide標記的API,其影響是什么? ? 做一個好的反射封裝,應注意什么問題,這種封裝的意義是什么? 第2章 Log是最簡單的代碼了,這里要講的是日志的高級知識: ? 打印日志的時機是什么,什么日志應該留在Release版本中,這么做是否安全? ? 如何區分不同項目組的日志,如何避免日志間的相互干擾? ? 如何優化和封裝日志,為什么說日志的分發功能是必須具備的? ? 微信是如何用MMAP提升日志的寫盤成功率的,Xlog的設計目的是什么? 第3章 Intent是非常簡單的對象,著重來講: ? 如何封裝和擴展Intent,為什么它只能存儲基本對象,Intent的本質是什么? ? 如何在使用Intent時避免管理Intent的Key,動態下發Intent的思路是什么? ? Intent的最大數據存放量是多少,該如何傳遞一個大對象? ? Intent傳遞map對象時會有什么隱患,linkedHashMap可以直接存入Intent嗎? 第4章 SharedPreferences作為基本的存儲對象,需要了解如下知識點: ? 用SharedPreferences存儲Java對象有什么問題,如何清理其緩存? ? 為什么拆分SharedPreferences后可以有效地減少內存的消耗? ? SharedPreferences的線程、進程安全嗎,它是如何引起ANR的? ? 如果將SharedPreferences中的數據放云端,該如何設計這種云同步的功能? 第5章 Fragment是開發者很容易出錯的類,這里需要思考: ? Fragment和Activity的生命周期是依次執行的嗎?動態添加時的生命周期會如何執行? ? Square不建議用Fragment,但不用Fragment的話,該如何模塊化地管理UI呢? ? Google公司提出的Lifecycle-Components和Fragment有關系嗎?使用的是什么原理? ? Fragment的嵌套和回退棧是一個難點,Jetpack中的Navigation是怎么簡化它的? 工程優化 工具是開發者的武器,擁有一個好的武器可以戰無不勝。在工程優化篇中,會提到如何利用工具和技巧幫助開發者優化項目。這部分的知識點較為零碎,但學起來并不難,很適合讀者用碎片時間進行學習。 第6章 Dialog已經不推薦直接使用了,取而代之的是dialogFragment,關于它我們需要知道: ? Dialog和alertDialog,alertDialog和dialogFragment是什么關系? ? 如何實現一個可以隨時展示的全局彈窗,這對于App的任務系統有什么好處? ? 為什么說完全可以通過Style實現自定義的Dialog,Dialog的背景該如何編寫? ? alertDialog引起內存泄露和崩潰的原因是什么,在開發中該如何防御? 第7章 Gradle是常用工具,本章不準備講它的基礎知識,會直接介紹實際的例子: ? 如何自動化生成versionCode和versionName,Gradle還能做哪些自動化處理? ? 如何強制整個App的某個庫均使用統一的版本號,如何更好地管理簽名文件? ? 如何引入本地的Maven倉庫,本地依賴的寫法是什么,如何制作一個本地庫? ? 如何使用Exclude Lib、Jar、Module等,對于產生類沖突的兩個庫該如何解決? 第8章 本章除講述如何提升打Debug包的速度外,還介紹了如下內容: ? 為什么小范圍的配置優化不如直接升級機器硬件來得快? ? Google廢棄compile()的原因是什么,新的依賴API有哪些,各有什么不同? ? 如何啟用Gradle緩存,減少每次編譯時的網絡請求是提速的關鍵嗎? ? Android有幾種簽名方案,不同簽名方案對應的多渠道打包策略有何不同? 第9章 每家公司都希望APK越來越小,本章探討的是切實有效的瘦身策略,主要解惑的點為: ? APK是由哪些文件組成的?APK和Zip是什么關系,簽名相關的文件在哪個目錄中? ? 瘦身開始前應該做哪些準備工作,為什么這個看似無關緊要的工作卻很重要。 ? APK中的.9圖應該放在哪個文件夾中,到底要不要做屏幕分辨率的適配。 ? ABI是什么意思,從云端下載so時需要注意什么問題,具體的可行性如何? 第10章 測試用例的編寫一直被我們忽視,本章是一個入門級的內容,涵蓋了如下的知識點: ? mock的目的是什么,常見的mock框架有哪些,我們一般會如何進行技術選型? ? 測試分為邏輯測試和UI測試,哪個才是移動測試的重點? ? 如果想要在PC端直接測試Android的邏輯,目前最方便的測試框架是哪個? ? 網絡層是一個典型的單元測試和集成測試的場景,該如何寫好異步代碼的測試用例? 第11章 本章在前半部分會講與Debug相關的內容,后半部分將介紹一些極其好用的插件,閱讀后你將知道: ? 如何在Debug時動態打Log,它和在代碼中硬編碼的Log有什么區別? ? 如何通過Debug工具檢查內存泄露,怎樣清楚地知道當前內存中的對象數目? ? Facebook的Sonar是什么,這個平臺可以帶來怎樣的想象力? ? 號稱史上最強的數據庫調試插件是什么,它真的值得購買嗎,免費的替代品是什么? 第12章 使用代理工具是開發人員和測試人員的必會技能,本章會介紹Whistle的主要功能: ? 支持用正則制定過濾規則,返回的JSON能自動進行格式化。 ? 支持為多個環境配置不同的代理,可以靈活地進行環境的切換。 ? 可以直接編寫mock規則,自動化地生成mock數據,并且能統一管理mock的values。 ? 支持調試Webview,可以很方便地進行真機上H5頁面的調試。 致謝 寫書本身是一件很嚴肅的事情,尤其是技術方面的書籍。我是一個討厭被限制的人,所以一直以來都是偷懶寫“網文”,原本不愿意出版圖書。下面要感謝一些朋友,沒有他們我可能永遠都無法邁出這一步,也無法得到一本真正屬于自己的作品。 ? 感謝博文觀點團隊的賞識和邀請,如果沒有貴團隊,我根本就不會有寫書的想法和機會。 ? 感謝本書的編輯陳曉猛,他的溝通能力和執行力是保障本書快速出版的關鍵。 ? 感謝“不吃魚同學”,要不是她的支持和鼓勵,我就沒有勇氣開始做這件長達一年的事情。 ? 感謝所有在微博關注我的朋友們,你們的支持和批評是鞭策我前進的動力。 ? 感謝聚美、網易和美團的一些朋友們,你們給予了我很多的建議和靈感。 ? 更要感謝即將開始閱讀本書的你,這本書就是為你而寫的,你的閱讀是我最大的榮耀! 聯系方式 如果你發現了本書的紕漏或是對內容有更好的建議,可以通過下列方式聯系到我。 |
內容簡介:本書從工程實踐角度詳細闡述了Android的知識內容,全書分為基礎知識和工程優化兩部分。在工程優化部分專門增加了常用的App編譯提速和瘦身的內容,對于大型分層項目的測試技巧也有所涉及。本書涵蓋Android開發的實際業務知識,涉及Dialog、Intent、Fragment等源碼的核心細節分析,并擴展了一部分框架設計的內容,章節最后總結了開箱即用的開源庫方案,實現從理論到實際的完整論述。最后還給出了抓包工具的使用技巧,幫助讀者能方便地尋找到適合自己的工具集。本書適合中、高級Android程序員閱讀,也可以作為初級程序員進階學習的參考書。 |
目錄:第1章 探尋高效易用的反射API 1.1 反射的能力 1.1.1 得到Class對象 1.1.2 操作Field 1.1.3 調用Method 1.1.4 動態代理 1.2 反射封裝庫——JOOR 1.2.1 反射的流程 1.2.2 VirtualApp中的反射 1.2.3 一行代碼建立對象 1.2.4 簡化Field的相關操作 1.2.5 簡化方法調用 1.2.6 封裝動態代理 1.3 注意事項 1.3.1 反射的性能問題 1.3.2 反射的使用時機 1.3.3 如何降低反射的性能損耗 1.3.4 反射的危險性 1.3.5 反射和混淆的關系 1.4 總結 第2章 打造高擴展性的Log系統 2.1 基本概念 2.2 命令行操作Log 2.2.1 輸出日志 2.2.2 過濾日志 2.3 Android Studio中的Log 2.3.1 設置模板 2.3.2 正則過濾 2.3.3 熱部署Log 2.4 微信的Xlog 2.4.1 設計和開發目標 2.4.2 編譯、引入和使用 2.4.3 對Log文件進行優化 2.5 美團的Logan 2.6 擴展Log的功能 2.6.1 TAG的自動化 2.6.2 文本內容的設計 2.6.3 開關的設計 2.7 封裝Log庫 2.7.1 Timber 2.7.2 LogDelegate 2.7.3 Logger 2.7.4 擴展Timber的功能 2.7.5 分發日志 2.8 實用日志 2.8.1 操作耗時日志 2.8.2 頁面跳轉日志 2.8.3 網絡請求日志 2.9 總結 第3章 萬變不離其宗的Intent 3.1 源碼分析 3.1.1 靜態變量的寫法 3.1.2 Intent的深拷貝 3.1.3 makeMainActivity 3.1.4 Intent的Chooser 3.1.5 用URI代替Intent 3.1.6 存取值的底層實現 3.1.7 區分顯式和隱式Intent 3.1.8 拋棄Bundle的傳值策略 3.2 序列化方案 3.2.1 Serializable/Externalizable 3.2.2 Android中的Parcelable 3.2.3 Google的Protocol Buffer 3.2.4 Twitter的Serial 3.3 常見問題 3.3.1 父類的序列化 3.3.2 類型轉換異常 3.3.3 重復啟動的問題 3.3.4 傳遞大對象 3.4 簡單的傳值庫——Parceler 3.4.1 降低Key的維護成本 3.4.2 自動維護Intent的Key 3.4.3 Jetpack中的自動化 3.4.4 自動保存狀態 3.4.5 處理ClassCastException 3.4.6 IntentLauncher 3.4.7 統一存取的API 3.5 總結 第4章 SharedPrefrences的再封裝 4.1 源碼分析 4.1.1 緩存機制 4.1.2 SharedPreferencesImpl 4.1.3 值操作 4.1.4 提交操作 4.2 異常處理 4.2.1 name為null 4.2.2 管理好Key的取名 4.2.3 清空操作失效 4.2.4 磁盤寫入異常 4.2.5 出現ANR 4.2.6 存序列化對象 4.2.7 多App和多進程訪問異常 4.3 性能優化 4.3.1 避免儲存大量數據 4.3.2 盡可能提前初始化 4.3.3 避免Key過長 4.3.4 多次操作,批量提交 4.3.5 緩存Editor對象 4.3.6 不存放HTML和JSON 4.3.7 拆分高頻和低頻操作 4.4 封裝SharedPreferences 4.4.1 PreferenceDataStore 4.4.2 通過接口提高內聚 4.4.3 得到SharedPreferences 4.4.4 多用戶存儲設計 4.4.5 統一管理Key 4.4.6 自動判斷返回值類型 4.4.7 決定是否使用Apply 4.4.8 存放序列化對象 4.4.9 支持數據格式轉換器 4.5 思維擴展 4.5.1 偏好界面的實現方案 4.5.2 監聽數據的改變 4.5.3 利用Tray實現多進程訪問 4.5.4 React Native中的使用 4.6 總結 第5章 尋找Fragment的繼任者 5.1 使用場景 5.1.1 日夜間模式 5.1.2 緩存界面數據 5.1.3 作為搜索頁 5.1.4 作為Presenter 5.2 源碼分析 5.2.1 Transaction簡介 5.2.2 提交操作 5.2.3 commitAllowingStateLoss 5.2.4 Add操作的原理 5.2.5 Replace操作的本質 5.2.6 Fragment的可見性監聽 5.2.7 ViewPager中的懶加載 5.3 常見問題 5.3.1 Activity為空 5.3.2 startActivityForResult 5.3.3 ViewPager的getItem 5.3.4 FragmentPagerAdapter 5.3.5 顯示一個對話框 5.3.6 重疊顯示的問題 5.3.7 Fragment的StateLoss 5.4 Fragment的替代品 5.4.1 Jetpack的Navigation 5.4.2 Square的Flow 5.4.3 簡化版的Fragment 5.5 Shatter庫 5.5.1 建立Shatter類 5.5.2 設計ShatterManager 5.5.3 分發生命周期 5.5.4 使用方式 5.6 總結 第6章 讓alertDialog為我所用 6.1 Dialog 6.1.1 Dialog和Window 6.1.2 Show和Dismiss方法 6.2 alertDialog 6.2.1 alertController 6.2.2 alertDialog.Bulder 6.3 dialogFragment 6.3.1 Fragment和Dialog 6.3.2 Show和Dismiss方法 6.4 實際問題 6.4.1 無法彈出輸入法 6.4.2 如何支持層疊彈窗 6.4.3 容易引起內存泄露 6.4.4 修改尺寸、背景和動畫 6.4.5 點擊后會自動關閉 6.4.6 在關閉或開啟時出現崩潰 6.5 封裝dialogFragment 6.5.1 用現成的alertParams 6.5.2 讓Builder類支持繼承 6.5.3 建立dialogFragment框架 6.6 easyDialog 6.6.1 基本用法 6.6.2 自定義一個Dialog 6.6.3 BottomSheetDialog 6.6.4 設置全局樣式 6.6.5 支持動態樣式 6.6.6 避免丟失監聽器 6.7 可全局彈出的Dialog 6.8 總結 第7章 Gradle的使用技巧 7.1 全局配置 7.1.1 設定UTF-8 7.1.2 依賴Google倉庫 7.1.3 支持Groovy 7.1.4 定義全局變量 7.1.5 配置Lint選項 7.2 操控Task 7.2.1 更改輸出的APK的名字 7.2.2 更改AAR輸出的位置 7.2.3 跳過AndroidTest 7.2.4 找出耗時的Task 7.2.5 抽離Task腳本 7.3 動態化 7.3.1 動態設置buildConfig 7.3.2 填充Manifest中的值 7.3.3 讓buildType支持繼承 7.3.4 讓Flavor支持繼承 7.3.5 內測版本用特定的Icon 7.3.6 不同渠道不同包名 7.3.7 自動填充版本信息 7.4 遠程依賴 7.4.1 配置Maven倉庫 7.4.2 依賴相關的API 7.4.3 組合依賴 7.4.4 依賴傳遞 7.4.5 動態版本號 7.4.6 強制版本號 7.4.7 exclude關鍵字 7.4.8 依賴管理 7.5 本地依賴 7.5.1 引用AAR 7.5.2 依賴Module/Jar 7.5.3 自建本地倉庫 7.5.4 本地依賴React Native 7.5.5 重新打包第三方Jar 7.6 資源管理 7.7 總結 第8章 縮減APK的編譯時間 8.1 分析項目現狀 8.1.1 Gradle Profile 8.1.2 BuildTimeTracker 8.1.3 Dexcount GradlePlugin 8.1.4 經驗小結 8.2 編譯環境優化 8.2.1 升級硬件設備 8.2.2 升級軟件 8.2.3 優化工程配置 8.2.4 配置Studio的可用內存 8.2.5 提升JVM的堆內存 8.2.6 開啟并行編譯 8.2.7 啟用Demand模式 8.2.8 配置DexOptions 8.3 善用緩存 8.3.1 減少動態方法 8.3.2 硬編碼BuildConfig和Res 8.3.3 拆分腳本 8.3.4 拆分代碼 8.3.5 寫死庫的版本號 8.4 精簡工程 8.4.1 差異化加載Plugin 8.4.2 使用WebP和SVG 8.4.3 精簡語言和圖片資源 8.4.4 善用no-op 8.4.5 Exclude無用庫 8.4.6 刪減Module 8.4.7 去掉MultiDex 8.4.8 刪除無用的資源 8.5 綜合技巧 8.5.1 構建開發時的Flavor 8.5.2 優化MultiDex 8.5.3 跳過無用的Task 8.5.4 關閉AAPT的圖片優化 8.5.5 調試時關閉Crashlytics 8.5.6 謹慎使用AspectJ 8.6 多渠道打包工具 8.6.1 MultiChannelPackageTool 8.6.2 美團的Walle 8.6.3 騰訊的VasDolly 8.7 總結
第9章 APP終極瘦身實踐 9.1 安裝包的構成 9.1.1 Assets 9.1.2 Lib 9.1.3 Resources.arsc 9.1.4 META-INF 9.1.5 Res 9.1.6 Dex 9.2 優化Assets目錄 9.2.1 刪除無用的字體 9.2.2 減少IconFont的使用 9.2.3 動態下載資源 9.2.4 壓縮資源文件 9.3 優化Lib目錄 9.3.1 配置ABI Filters 9.3.2 根據CPU引入so 9.3.3 動態加載so 9.3.4 避免復制so 9.3.5 謹慎處理so 9.4 優化Resources.arsc 9.4.1 刪除無用的映射 9.4.2 進行資源混淆 9.5 優化META-INF 9.5.1 MANIFEST.MF 9.5.2 CERT.SF 9.5.3 CERT.RSA 9.5.4 優化建議 9.6 優化Res目錄 9.6.1 通過IDE刪除無用資源 9.6.2 打包時剔除無用資源 9.6.3 刪除無用的語言 9.6.4 控制Raw中的資源大小 9.6.5 減少Shape文件 9.6.6 減少Menu文件 9.6.7 減少Layout文件 9.6.8 動態下載圖片 9.6.9 分目錄放置圖片 9.6.10 合理使用圖片資源 9.6.11 丟棄特定的資源 9.6.12 開啟嚴格模式 9.6.13 移除Lib庫中的配置文件 9.7 優化圖片資源 9.7.1 使用VectorDrawable 9.7.2 使用WebP 9.7.3 替換support庫中的圖 9.7.4 精簡動畫圖片 9.7.5 復用相同的Icon 9.7.6 使用Tint 9.7.7 復用按壓效果 9.7.8 通過旋轉復用 9.8 優化Dex 9.8.1 分析Dex 9.8.2 利用Lint分析無用代碼 9.8.3 刪除R文件 9.8.4 啟用ProGuard 9.8.5 使用拆分后的support庫 9.8.6 盡量不用Mulitdex 9.8.7 使用更小庫或合并現有庫 9.8.8 根據環境依賴庫 9.9 總結 第10章 編寫針對性的TestCase 10.1 基礎概念 10.1.1 什么代碼應被測試 10.1.2 編寫易于被測試的代碼 10.1.3 測試框架的選型 10.2 邏輯測試 10.2.1 Junit測試 10.2.2 Mockito 10.2.3 Robolectric的使用 10.2.4 Espresso 10.3 集成測試網絡層 10.3.1 編寫網絡層邏輯 10.3.2 建立測試對象 10.3.3 測試HTTP的異常情況 10.3.4 測試業務代碼的正確性 10.3.5 用Interceptor模擬返回值 10.4 總結 第11章 Android Studio使用經驗 11.1 調試篇 11.2 插件篇 11.2.1 統計相關 11.2.2 工具相關 11.3 總結 第12章 抓包工具Whistle實踐 12.1 抓包工具 12.1.1 Charles 12.1.2 Fiddler 12.1.3 AnyProxy 12.1.4 Whistle 12.2 Whistle的安裝和使用 12.2.1 安裝和更新 12.2.2 查看Request和Response 12.2.3 代理技巧 12.2.4 過濾規則 12.3 Whistle的各項功能 12.3.1 替換域名 12.3.2 修改請求參數 12.3.3 修改返回值 12.3.4 模擬低網速的情形 12.3.5 查看WebView的Console 12.4 總結 |
序: |