FPS : 1s 內(nèi) SurfaceFLinger 提交到屏幕的幀數(shù)。
FPS 很低亚再,但是不卡亲茅。 是因為你的 app 在這 1s 內(nèi)只有 30 幀的顯示需求颁股; 如果沒有繪制需求, FPS 就是 0盹廷;
App 停止操作后 FPS 還在變化征绸, 是因為每一幀的合成是針對手機所有進程的, 即使你的 app 停止了繪制俄占,其他的進程可能還在繪制管怠,例如通知欄;
如何評測流暢度缸榄?
FPS 評測流暢度并不準確渤弛,那么應(yīng)該找到一個什么樣的指標進行評測呢?
Android 4.1 引入了 VSync 機制甚带。
VSync 機制就像一臺轉(zhuǎn)速固定的發(fā)動機(60轉(zhuǎn)/s)她肯,每一轉(zhuǎn)帶動著做一些 UI 相關(guān)的事情佳头。有時候因為各種阻力, 某一圈的工作量比較重辕宏, 超過了 16.6ms, 那么這一秒內(nèi)就不是 60 轉(zhuǎn)了畜晰。
我們通過測量這個轉(zhuǎn)速,來評判應(yīng)用的流暢度
Android 系統(tǒng)中瑞筐, Choreographer 類通過監(jiān)聽系統(tǒng) VSync 信號來協(xié)調(diào) App 的動畫、輸入腊瑟、繪制工作聚假。 它本身是單例模式。
丟幀計算:在一次 Loop 時闰非,如果執(zhí)行時間超過了 16.6ms, 那么多余 16.6ms 的時間除以 16.6ms, 即是當(dāng)前 App 的丟幀情況膘格。
注冊 Choreographer callback 事件, 在每一幀繪制完成后财松, 執(zhí)行回調(diào)
Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
//do calculate
Choreographer.getInstance().postFrameCallback(this);
}
});
流暢度值計算:
SM = 幀率(60) * (單位時長總幀數(shù) - 單位時長丟幀數(shù)) / 單位時長總幀數(shù)
評測標準:
SM值 | 卡頓情況 |
---|---|
SM <= 20 | 卡死 |
20 < SM <= 40 | 很卡 |
40 < SM <= 50 | 較卡 |
50 < SM <= 60 | 流暢 |
如何優(yōu)化
避免過度繪制
設(shè)置中開發(fā)者選項打開過度繪制區(qū)域查看瘪贱。
OverDraw 倍數(shù) | 像素點繪制次數(shù) | 可接受區(qū)域 | |
---|---|---|---|
無色 | 0X | 1 | 全局 |
藍色 | 1X | 2 | 大片 |
綠色 | 2X | 3 | 中等 |
淺紅 | 3X | 4 | 小,少 |
暗紅 | 4X | ≥ 5 | 無 |
解決 UI 布局中不合理的地方
- 減少布局層次辆毡, 利用 <merge> <ViewStub> 消除無用的父布局
- 不常用的 UI 設(shè)置成 GONE
- 靈活使用 ConstraintLayout
Lint 掃描
優(yōu)化邏輯
- TraceView 尋找卡住主線程的地方
- Systrace 獲取 app 運行是線程的信息以及 API 的執(zhí)行情況
- 避免在主線程執(zhí)行 IO 操作
- 優(yōu)化布局結(jié)構(gòu)
- 盡量多使用 RelativeLayout 和 LinearLayout
- 在布局層次一樣時菜秦,LinearLayout 比 RelativeLayout 性能稍高一點
- 相對復(fù)雜的而不懼, RelativeLayout 可以比 LinearLayout 減少層級
- 可復(fù)用的組件抽取處理啊通過 include 標簽使用
- 使用 ViewStub 標簽來加載一些不常用的布局
- 使用 merge 標簽減少布局的嵌套層次
- 去掉多余的背景顏色舶掖,減少過度繪制
- 盡量多使用 RelativeLayout 和 LinearLayout
Github 上找到的一個 SM 庫實現(xiàn):
https://github.com/friendlyrobotnyc/TinyDancer