整理自網絡
Android性能 - 啓動
-
Android程序的啓動分類
-
冷啓動
- 加載啓動app
- 展示空白window頁面
- 創建app進程
- 創建app對象
- 啓動主線程
- 創建啓動activity對象
- 加載view
- 佈置屏幕
- 第一次繪製
-
啓動優化方向
-
替換window頁面背景 <障眼法>
-
避免啓動的密集初始化
常常使用的multiDex初始化,第三方組件初始化
利用歡迎頁和閃屏頁時間完成初始化
-
避免耗時操作和深嵌套佈局
-
Android性能 - 佈局
由於任何原因導致接收到VSYNC信號的時候無法完成本次刷新操作,就會產生掉幀的現象
- 過度繪製
-
解決
- 去掉佈局的背景色
- 去掉不必要控件的背景色
-
GPU渲染
- 橙色 :GUP做的任務
- 紅色 :繪製視圖的多少
- 淺藍色 :繪製圖片
- 深藍色 :更新視圖
- 綠色1 :佈局測量
- 綠色2 :動畫
- 綠色3 :輸入處理
- 深綠色: 主線程耗時操作
Android性能 - 內存 (一)
-
Java內存
- 方法區:常量,類信息 <線程共享>
- 虛擬棧:每個方法由棧幀,存儲方法信息 <線程私有,爲Java方法服務>
- 本地棧:爲本地方法服務
- 堆: 對象實例所在<線程共享>
- 程序計數器: 所執行的字節碼行號指示器 <Java方法擁有,本地方法爲空>
-
Java內存回收
-
標記清除 : 標記回收對象,清除被標記對象 <易產生大量碎片>
-
複製算法 :內存一分爲二,一個現用,一個備用 <實際可用內存大小縮小爲一半>
-
標記整理: 標記回收對象,整理(移動)存活對象 <避免內存碎片,避免一半內存的浪費 針對對象存活率較高的老年代>
-
分代收集: 根據對象的生命週期劃分內存
堆:
新生代 ->大量對象死亡 -> 複製算法
老年代 ->對象存活率高 -> 標記算法
-
-
對象是否回收
-
引用計數
引用對象,計數+1
引用失效,計數 - 1
缺點:不能解決相互循環引用
-
可達性分析
以GCroot對象爲根節點
有可達引用鏈表示對象存活
-
-
Android內存
-
Dalvik虛擬機
- 加入JIT即時編譯策略: 缺點①每次啓動應用都要編譯②運行時更耗電
-
ART虛擬機
- AOT編譯策略,靜態編譯,安裝程序的時候編譯
- 改進GC過程
-
兩者混合編譯
- 程序安裝時dex不會被編譯
- 運行時編譯dex
- 手機充電或者空閒時進行AOT編譯
-
內存回收
新生代->老年代->永久代
-
共享內存
Zygote的進程fork出來的程序進程
-
分配和回收內存
-
Android性能 - 卡頓
60幀合適的顯示速度,16ms內顯示界面佈局表示流暢畫面
卡頓時候,幀率下降到30等,很明顯的卡頓
卡頓的原因
- UI線程中的耗時操作
- I/O讀寫
- 數據庫訪問
- 網絡請求
- 佈局不合理
- 控件數量多
- 嵌套深
- overdraw
- 內存異常
- 內存泄漏
- GC次數多 <那麼CPU繪製時間就短>
- 錯誤的異步操作
- 異步線程開啓失誤
尋找卡頓
原因
-
stick mode
檢測程序中違例的情況
- 主線程進行I/O操作
- 主線程進行網絡請求
主要檢測兩大問題
- 線程策略 <線程使用不當>
- VM策略 <內存泄漏>
使用
if (IS_DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()); StrictMode.setVmPolicy(new VmPolicy.Builder().detectAll().penaltyLog().build()); }
在debug模式下使用
查看日誌
Android性能 - 異步
異步不包治百病,不正確使用異步會更卡頓
線程調度
- nice values線程優先級
- default UI線程
- background 後臺線程
- cgroups
- 控制和分離進程組
- 使用
new Thread(new Runannable()).start()
創建和銷燬耗能大
和UI線程具有相同的優先級,出現競爭
匿名內部類持有外部引用,易內存泄漏
缺乏線程管理
private class A extendes AysncTask<in,progress,result>{
onPreExecute();//執行任務前
doInBackground();//線程後臺任務
onProgressUpdate();//任務進度
onPostExecute();//UI操作
onCancelled();//取消異步操作
}
in 傳入的參數
progress 進度
result 結果
默認串行
匿名內部類持有外部引用,內存易泄漏
Handler handler = new Handler(){
handleMessage(msg);
};
串行執行
默認優先級和UI線程同級,出現競爭
IntentService
ThreadPoolExecutor
Android性能 - 瘦身
-
APK組成
- assets/ 靜態文件
- lib/ os文件
- META-INF/ 簽名信息
- res/ 資源文件
- AndroidManifest.xml 配置文件
- classes.dex Java字節碼的產物
- resource.arsc 編譯後的二進制資源文件
-
AS自帶的 analyze APK工具
-
反編譯工具 class shark
https://github.com/google/android-classyshark/releases
-
如何瘦身
-
移除無用代碼
-
移除無用庫,相同庫
-
啓用Proguard
稍用,規則繁瑣
-
縮減方法數
-
移除無用資源
layout
drawable
-
圖片壓縮
壓縮網站 https://tinypng.com/
AndroidStudio插件:TinyPngPlugin,能夠批量地壓縮項目中的圖片,更加方便。
-
png轉jpg
png無損
png體積大
-
使用矢量圖
xml, svg
-
使用webp
-
網絡資源
-
so文件瘦身
-
使用7zip進行極限壓縮
Android性能 - 電量
-
工具 Battery Historian
-
電量優化
-
CPU時間片
-
網絡傳輸
數據壓縮
傳輸方式
請求處理
無網避免請
-
GPS
合適的location provider
及時註銷監聽
模塊複用
-
wake lock 不休眠鎖
-
傳感器
-
Android性能 - 網絡
- 網絡問題
- 流量消耗
- 電量消耗
- 熱修復
- 弱網
- 網絡監控
- network monitor 網絡請求
- fiddler charles 抓包
- 優化方向 <速度,流量,成功率>
- gzip壓縮減少傳輸
- IP直連去除DNS解析
- webp格式的圖片
- 縮略圖
- 網絡緩存
- 弱網判斷特殊處理
Android性能 - 無響應
- 分類
- 觸摸或按鍵等待
- 廣播不能規定完成
- 服務不能規定完成
- 原因
- 主線程阻塞
- IO等待
- 其他程序影響
- 出發場景
- 輸入5s未響應完畢
- 前臺廣播10s內未完畢,後臺20s
- 前臺服務20s,後臺服務200s
- 內容提供者publish 10s
Android性能 - Bitmap
-
bitmap內存模型
Android2.2之前GC執行,主線程暫停;
Android2.3之後,GC併發執行
API 10 bitmap像素數據存放在 native內存,對象在dalvik heap;
3.0~8.0 像素和對象都在native內存;
8.0~now 像素又移到了native,對象和像素可以同時回收,新增hardware bitmap
-
bitmap回收
2.2.3之前推薦使用bitmap.recycle()
3.0之後複用bitmap
-
bitmap的複用
-
bitmap的加載
-
推薦使用圖片加載框架glide,piccasso等處理圖片