Android開發:30條Android開發建議
《億級 Android 架構》 地址:https://xiaozhuanlan.com/topic/1934527806
There are two kinds of people : those who learn the hard way and those who learn by taking someone’s advice.
轉載自:https://www.jianshu.com/p/717b80ba8bc1?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io
當前Android開發領域最佳實踐方案,覆蓋了最新的技術、架構等各種細節。
本文主要用來收集Android開發中積累的一些寶貴經驗,這些經驗中有一些約定熟成且經過檢驗的建議,有一些結合最新技術的實踐。無論是菜鳥還是大神,都應該學會閱讀別人的經驗,並結合自己的思考轉化成對自己有用的知識,這才是最快的成長之路。另外,對於這些建議,我會盡量翔實的進行說明以確保能夠順利快速應用到實際開發中。
介紹
下面以這篇文章:Building Android Apps — 30 things that experience made me learn the hard way為核心,對其中提出的每一點建議進行較為深入的分析探究,最終整理成一篇完整的文章。當然,本文還在不斷更新中。
1. 第三方庫
在你新增每一個third party library之前,請認真考慮是否真的需要這個library。
2. OverDraw
如果使用者看不到,那就不要進行繪製(draw),或者說,不要過度繪製 OverDraw
OverDraw
會導致GPU浪費,也會導致app的速度變慢。為了減少這種危害,我們可以利用Debug GPU Overdraw Tool
來觀察app裡的繪製情況,然後可以使用Hierarchy Viewer來進行優化。
3. 資料庫
除非不得不,否則不要使用database
4. 65k methods limit
Dalvik 65K methods limit
multidexing
會幫助你。什麼是
Dalvik 65K methods limit
?我們知道,我們寫完java code之後,dx tool會把java編譯成Dalivik虛擬機器能識別的DEX
檔案,這個檔案裡最多能夠索引65536個method
。關於這個有兩點要注意:
- 這些method是指能夠
索引(reference)
到的,而不是定義(define)
的。或者說,如果你定義了一個方法,但這個方法並沒有被呼叫,那麼就不算在內。 - 這些method不僅僅是開發人員自己寫的,還包括所有第三方library裡面的method。
所以,我們總共可以索引65536
個方法,包括自己寫的和引入第三方庫裡的。
那麼,我們如何能快速知道我們的app裡已經有多少個method了呢?
- bash script: dex-method-counts。這個工具可以快速計算,並且提供一個清晰的檢視來閱讀。
- dex.sh by Jake Wharton。這個工具由於採用了遞迴演算法,所以耗時比較長。(Jake大神還寫了一篇有趣的分析文章Play Services 5.0 Is A Monolith Abomination,針對Play Services 5.0太大的問題進行了分析,有空時我再翻譯下給各位。雖然Play Services 6.5已經模組化,更加輕量級了)。
現在,既然我們已經知道了自家app裡的method數了,那麼如何來處理這種情況呢?
- Multidex,官方提供的解決方案,這篇文章裡有詳細的使用方法,此不贅述。
- ProGuard
ProGuard
可以把code裡unnecessary的method移除,壓縮apk,當然還有程式碼混淆
的奇效。 - 再建立一個
DEX File
。把app裡可以獨立的模組或code提取出來,放到一個獨立的dex檔案裡,你可以使用Custom ClassLoader來載入這些類,然後使用介面
或反射
來呼叫這些方法。不過,這個過程還是比較麻煩的。
5. RxJava+RxAndroid+Retrolambda
使用前可以通過這篇gist來了解RxJava, RxAndroid & Retrolambda
的結合用法。這個組合可以優雅的在不同執行緒中處理事務,同時能夠方便的實現資料流動和及時響應,而且Retrolambda能夠精簡你的code。其中,核心的兩個概念是Observables
和Subscribers
,前者對外提供資料,後者監聽並消費這些資料。
另外,這裡有一個看起來不錯的專案Learning RxJava for Android by example,等空閒時再去閱讀下code。
6. Retrofit + RxJava
利用Retrofit與RxJava結合,為你的app提供網路請求服務。
你可以參考這個超讚的例子,讓你快速感受二者結合使用方法。
7. 按feature
來分package,而不是按layer
這是這篇文章提出的一個點,文中認為分package就像公司安排座位,要按照team
來分而不是按照每個人的職位來分,即按照負責一個app的developer、designer、pm
坐在一起,而不是把所有developer
坐在一起,所有designer
坐在一起。所以,原文作者認為把一個feature相關的如Activity
adapter
等都放在一起。
不過,我認為按feature也有壞處,那就是複用
,拿adapter來講,一個app裡很多adapter是類似且可以複用的,如果我們把各個adapter拆倒各個角落裡,就很難提取其中的關聯來建立一個BaseAdapter
了。而且,不同feature之間也有很多公用的東西
,比如一個自定義view,那就很難界定應該放在哪個feature包裡了。相反,我們把所有自定義view放在一起,這樣也有助於我們發現某些自定義view的區別,然後在refactor時可以提取公用的東西來複用
。
關於這點,歡迎讀者給出自己意見。
8. 加速Gradle
9. 架構:使用clean Architecture
這裡有兩篇優質文章:Architecting Android…The clean way?和Architecting Android…The evolution 分別介紹並用code實現了一個Clean架構。後面我也會專門分析下這種架構,因為對於任何一個project而言,最初的好的架構是非常重要的!所以,如果你想提高自己,那麼架構
這一關是必經之路。
10. 測試你的app
雖然做測試需要花費你不少時間,但一旦你完成了這一步,以後的開發會更加快速,app也會更加穩定。
這裡有個哥們,對unit test
進行了細緻的點評。
11. 使用依賴注入
神器Dagger
如果你不知道什麼是依賴注入
,你可以先讀一下這篇文章Dependency injection on Android: Dagger (Part 1),或者這篇依賴注入。簡單來說,依賴注入替代了傳統建立物件的new
操作,當需要建立一個class的例項時,使用依賴注入從外部直接獲取一個例項,具體這個例項是如何建立的不需要關心,由一個物件庫統一管理每個物件的建立過程,並直接對外提供物件。這樣做的好處是我們不用管例項是怎麼建立的,這種抽象可以使得每個物件的建立過程變得可擴充套件性,只要在物件庫裡修改一次,那麼所有用到這個例項的地方都隨之變更。例如在測試時,我們希望某個mock某個物件的資料,就可以修改注入的物件。
依賴注入有不少工具,不過Dagger2使用的是編譯時程式碼生成(code generation)
方式而不是反射(reflection)
,所以它的效能比較出眾。這篇文章有對Dagger2的實踐和分析。
13. 關注新的開源library
你可以通過Android Arsenal來保持對開源專案的關注,同時利用這個工具dryrun來快速將開源專案跑在genymotion以看到實際效果。
14. Service
如果你建立了Service,那麼一旦這個Service完成了自己的使命,就應該立即清理掉它
15. 使用AccountManager來統一管理使用者的帳號密碼。
16. 使用持續整合CI(Continuous Integration)
來編譯併發布你的beta和release build
持續整合可以幫助你方便的編譯併發布專案,不過,不要去搭建你們自己的CI伺服器,因為你需要花費太多的時間來處理硬碟空間、安全問題和預防SSL攻擊等問題。你可以嘗試Jenkins、circleci、 travis 或者 shippable,這些價格並不貴,而且能幫你省很多事情。
17. 自動釋出到Play Store
你可以使用這個工具gradle-play-publisher來幫助你自動上傳apk到Play Store上
18. 開始考慮用svg替代png
理由很簡單,android developer應該很熟悉每次匯入一張圖片時都需要生成四五種不同大小的png圖片並放入到對應資料夾。與其維護這麼多圖片,顯然使用一張svg圖片更加方便。而且,google也在不斷提供相關的支援,除了基本的Vector Drawable,從最新的Support Library我們也能看到google也在鼓勵developer們使用svg。
不過,svg也有自己的限制,比如它比較適合小icon,因為它最終會生成bitmap載入以供顯示,所以這需要一定的cpu支援。當然總體來講svg還是更優的,至少大家可以不用再維護四五張不同尺寸的圖片了。
19. 將一些library的類進行抽象,從而方便後期替換library
例如,一旦我們打log會使用Log.i()
,但是,如果後面我們突然想換成Timber.i()
就會很麻煩,需要一個個log找到來替換。但是,如果我們抽象出一個AppLogger
來,全部呼叫AppLogger.i()
來記log,那麼我們只要簡單的在AppLogger
內部替換掉具體實現就可以了。
20. 監控網路連線型別,區分移動資料流量
和Wi-Fi
;同樣,可以監控電量
和充電狀態
對於不同網路型別,我們可以動態改變我們的UI,比如大圖可以選擇在Wi-Fi
下才載入,而在移動資料流量
則不載入。對於電量
也是類似的邏輯。使用者一定會很感謝app做的這種自適應的。
21. User Interface is like a joke.If you have to explain it, it's not that good.
22. 先寫slow但是right的程式碼,再去進行優化
小結
本文長期更新,會保持跟蹤最新的技術和研究實踐經驗,為大家提供有效有用的經驗,少走坑。
謝謝!