- http頭信息帶Cache-Control域 肯定緩存過時時間 防止重複請求
- 直接用IP直連,不用域名,策略性跟新本地IP列表。 – DNS解析過程耗時在百毫秒左右,而且還有可能存在DNS劫持。
- 圖片、JS、CSS等靜態資源,採用CDN(固然若是是使用7牛之類的服務就已經給你搭建佈置好了)
- 全局圖片處理採用漏斗模型全局管控,所請求的圖片大小最好依照業務大小提供/最大不超過屏幕分辨率須要,若是請求原圖,也不要超過
GL10.GL_MAX_TEXTURE_SIZE
- 全局縮略圖直接採用webp,在儘量不損失圖片質量的前提下,圖片大小與png比縮小30% ~ 70%
- 若是列表裏的縮略圖服務器處理好的小圖,能夠考慮直接在列表數據請求中,直接以base64在列表數據中直接帶上圖片(國內還比較少,海外有些這種作法,好像web端比較常見)
- 輪詢或者socket心跳採用系統
AlarmManager
提供的鬧鐘服務來作,保證在系統休眠的時候cpu能夠獲得休眠,在須要喚醒時能夠喚醒(持有cpu喚醒鎖)
- 能夠經過將零散的網路的請求打包進行一次操做,避免過多的無線信號引發電量消耗。
1. 傳輸數據格式選擇
2. 輸入流
使用具備緩存策略的輸入流html
原 |
建議替換爲 |
InputStream |
BufferedInputStream |
Reader |
BufferedReader |
II. 數據結構
若是已知大概須要多大,就直接給初始大小,減小擴容時額外開銷。android
1. List
ArrayList
裏面就一數組,內存小,有序取值快,擴容效率低git
LinkedList
裏面就一雙向鏈表,內存大,隨機插入刪除快,擴容效率高。github
2. Hash
HashSet
裏面就一個HashMap
,用key對外存儲,目的就是不容許重複元素。web
ConcurrentHashMap
線程安全,採用細分鎖,鎖顆粒更小,併發性能更優數據庫
Collections.synchronizedMap
線程安全,採用當前對象做爲鎖,顆粒較大,併發性能較差。編程
3. Int做爲Key的Map
針對該特性進行了優化,採用二分法查找,簡單數組存儲。json
SparseArray
、SparseBooleanArray
、SparseIntArray
。api
III. 數據庫相關
建多索引的原則: 哪一個字段能夠最快的減小查詢結果,就把該字段放在最前面數組
沒法使用索引的狀況
- 操做符
BETWEEN
、LIKE
、OR
- 表達式
CASE WHEN
不推薦
- 不要設計出索引是其餘索引的前綴(沒有意義)
- 更新時拒絕直接全量更新,要更新哪列就put哪列的數據
- 若是最頻繁的是更新與插入,別建不少索引 (本來表就很小就也不必建)
- 拒絕用大字符串建立索引
- 避免建太多索引,查詢時可能就不會選擇最好的來執行
推薦
- 多使用整型索引,效率遠高於字符串索引
- 搜索時使用SQL參數(
"?", parameter
)代替字符串拼接(底層有特殊優化與緩存)
- 查詢須要多少就limit多少(如判斷是否含有啥,就limit 1就好了嘛)
- 若是出現很寬的列(如blob類型),考慮放在單獨表中(在查詢或者更新其餘列數據時防止沒必要要的大數據i/o影響性能)
IV. JNI抉擇
Android JVM相關知識,可參看: ART、Dalvik
Android JNI、NDK相關知識,可參看: NDK
JNI不必定顯得更快,有些會更慢。
特色: 不用在虛擬機的框子下寫代碼
- 能夠調用更底層的高性能的代碼庫 – Good
- 若是是Dalvik,將省去了由JIT編譯期轉爲本地代碼的這個步驟。 – Good
- Java調用JNI的耗時較Java調用Java確定更慢,雖然隨着JDK版本的升級,差距已經愈來愈小(JDK1.6版本是5倍Java調用Java方法的耗時) – Bad
- 內存不在Java Heap,沒有OOM風險,有效減小gc。 – Good
一些重要的參數之類,也能夠考慮放在Native層,保證安全性。參考: Android應用程序通用自動脫殼方法研究
V. 多進程抉擇
360 17個進程: 360手機衛士 Android開發 InfoQ視頻 總結
- 充分獨立,解耦部分
- 大內存(如臨時展現大量圖片的Activity)、沒法解決的crash、內存泄漏等問題,考慮經過獨立進程解決
- 獨立於UI進程,須要在後臺長期存活的服務(參看Android中線程、進程與組件的關係)
- 非己方第三方庫(沒法保證穩定、性能等問題,而且獨立組件),可考慮獨立進程
最後,多進程存在的兩個問題: 1. 因爲進程間通信或者首次調起進程的消耗等,帶來的cpu、i/o等的資源競爭。2. 也許對於部分同事來講,會還有可讀性問題吧,畢竟多了層IPC繞了點。
VI. UI層面
相關深刻優化,可參看Android繪製佈局相關
對於卡頓相關排查推薦參看: Android性能優化案例研究(上)與Android性能優化案例研究(下)
- 減小沒必要要的不透明背景相互覆蓋,減小重繪,由於GPU不得不一遍又一遍的畫這些圖層
- 保證UI線程一次完整的繪製(measure、layout、draw)不超過16ms(60Hz),不然就會出現掉幀,卡頓的現象
- 在UI線程中頻繁的調度中,儘可能少的對象建立,減小gc等。
- 分步加載(減小任務顆粒)、預加載、異步加載(區別出耗時任務,採用異步加載)
VII. 庫推薦
能夠參考Falcon Pro做者的推薦: Falcon Pro 3如何完成獨立開發演講分析
1. 代碼編寫習慣
RxJava (響應式編程,代碼更加簡潔,異步處理更快快捷、異常處理更加完全、數據管道理念)
相關了解能夠參看: RxJava
2. 圖片加載:
3. 網絡底層庫:
Okhttp: 默認gzip、緩存、安全等
4. 網絡基層:
Retrofit: 很是好用的REST Client,結合RxJava簡單API實現、類型安全,簡單快捷
5. 數據庫層:
Realm: 效率極高(Falcon Pro 3的做者Joaquim用了該庫之後,全部數據庫操做都放到了UI線程)(基於TightDB,底層C++閉源,Java層開源,簡單使用,性能遠高於SQLite等)
6. Crash上報:
Fabric: 全面的信息(新版本還支持JNI Crash獲取和上報)、穩定的數據、及時的通知、強大的反混淆(其實在混淆後有上傳mapping)
7. 內存泄漏自動化檢測
LeakCanary: 自動化泄漏檢測與分析 ( 能夠看看這個LeakCanary使用總結與Leakcanary Square的一款Android/Java內存泄漏檢測工具)
8. 其餘
VIII. 內存泄漏相關
- 沒法解決的泄漏(如系統底層引發的)移至獨立進程(如2.x機器存在webview的內存泄漏)
- 大圖片資源/全屏圖片資源,要不放在
assets
下,要不放在nodpi
下,要不都帶,不然縮放會帶來額外耗時與內存問題
- 4.x在AndroidManifest中配置
largeHeap=true
,通常dvm heep最大值可增大50%以上。
- 在
Activity#onDestory
之後,遍歷全部View,幹掉全部View可能的引用(一般泄漏一個Activity,連帶泄漏其上的View,而後就泄漏了大於全屏圖片的內存)。
- 萬金油: 靜態化內部類,使用
WeakReference
引用外部類,防止內部類長期存在,泄漏了外部類的問題。
圖片Decode
- 全局統一
BitmapFactory#decode
出口,捕獲此處decode oom,控制長寬(小於屏幕分辨率大小 )
- 若是採用RGB_8888 oom了,嘗試RGB_565(相比內存小一半以上(wh2(bytes)))
- 若是還考慮2.x機器的話,設置
BitmapFactory#options
的InNativeAlloc
參數爲true,此時decode的內存不會上報到dvm中,便不會oom。
IX. 編譯與發佈
- 考慮採用DexGuard,或ProGuard結合相關資源混淆來提升安全與包大小,參考: DexGuard、Proguard、Multi-dex
- 結合Gradle、Gitlab-CI 與Slack(Incoming WebHooks),快速實現,打相關git上打相關Tag,自動編相關包通知Slack。
- 結合Gitlab-CI與Slack(Incoming WebHooks),快速實現,全部的push,Slack快速獲知。
- 結合Gradle中Android提供的
productFlavors
參數,定義不一樣的variations,快速批量打渠道包
X. 其餘
final
能用就用(高效: 編譯器在調用final
方法時,會轉入內嵌機制)
- 懶預加載,如簡單的ListView、RecyclerView等滑動列表控件,停留在當前頁面的時候,能夠考慮直接預加載下個頁面所需圖片
- 智能預加載,經過權重等方式結合業務層面,分析出哪些更有可能被用戶瀏覽使用,而後再在某個可能的時刻進行預加載。如,進入朋友圈以前經過用戶行爲,智能預加載部分原圖。
- 作好有損體驗的準備,在一些沒法避免的問題面前作好有損體驗(如,非UI進程crash,能夠本身解決就不要讓用戶感知,或者UI進程crash了,作好場景恢復)
- 作好各項有效監控:crash(注意還有JNI的)、anr(按期掃描文件)、掉幀(繪製監控、activity生命週期監控等)、異常狀態監控(本地Log根據須要不一樣級別打Log並選擇性上報監控)等
- 文件存儲推薦放在
/sdcard/Android/data/[package name]/
裏(在應用卸載時,會隨即刪除)(Context#getExternalFilesDir()
),而非/sdcard/
根目錄建文件夾(節操問題)
- 經過gradle的
shrinkResources
與minifyEnabled
參數能夠簡單快速的在編包的時候自動刪除無用資源
- 因爲resources.arsc在api8之後,aapt中默認採用UTF-8編碼,致使資源中大都是中文的resources.arsc相比採用UTF-16編碼更大,此時,能夠考慮aapt中指定使用UTF-16
- 谷歌建議,大於10M的大型應用考慮安裝到SD卡上: App Install Location
- 固然運維也是一方面: Optimize Your App
- 在已知而且不須要棧數據的狀況下,就沒有必要須要使用異常,或建立
Throwable
生成棧快照是一項耗時的工做。