Android 系統每隔 16ms 會發出 VSYNC 信號重繪界面(Activity)。之所以是 16ms,是因為 Android 設定的刷新率是 60FPS(Frame Per Second),也就是每秒 60 幀的刷新率,約合 16ms 刷新一次。
這就意味著,我們需要在 16ms 內完成下一次要刷新的界面的相關運算,以便界面刷新更新。
假設我們更新屏幕的背景圖片需要 24ms 來做這次運算,當系統在第一個 16ms 時刷新界面,由于運算還沒有結束,無法繪出圖片。當系統隔 16ms 再發一次 VSYNC 信息重繪界面時,用戶才會看到更新后的圖片。也就是說 32ms 后才看到了這次刷新(并不是 24ms),這就是丟幀(dropped frame)。
丟幀給用戶的感覺就是卡頓,而且如果運算過于復雜,丟幀會更多,導致界面常常處于停滯狀態。
卡頓原因
過于復雜的布局
過度繪制
UI 線程的復雜運算
頻繁的 GC
優化方法
1、減少刷新次數
比如進度更新,要進度有變化再去刷新,且保證頻率不得高于系統的刷新頻率。
2、避免非必要的刷新
若控件不可見,則無需刷新。
3、避免后臺線程影響
如列表控件,在滑動時不要去加載圖片,可以在滑動監聽里停止圖片的加載。
4、局部刷新
如 RecyclerView 的 DiffUtil。自定義 View 可以使用下面兩個方法:
invalidate(Rect dirty);invalidate(int left, int top, int right, int bottom);
5、盡量使用屬性動畫,它減少了自身的重繪。最后要清除
StringBuilder,List 等在創建時傳入一個合適的參數指定初始容量,以避免頻繁擴容的開銷。
6、開啟硬件加速
7、原理可見 Android硬件加速原理與實現簡介,理解Android硬件加速原理的小白文
Application 級別
<application android:hardwareAccelerated="true" />
Activity 級別
<activity android:hardwareAccelerated="true" />
Window 級別
getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
View 級別
// 如果是 software,會將 View 繪制到一個 Bitmap,// 然后依然是通過硬件加速將 Bitmap 繪制到 Canvasview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
檢查是否開啟了硬件加速
view.isHardware-Accelerated();Canvas.isHardwareAccelerated();
如果 View 中要處理中文長文本,需要關閉硬件加速。因為每個中文編碼不一樣,緩存效果不理想。
監控
ANR
Activity 的 View:5 秒無響應
BroadcastReceiver:10 秒無響應
Service:20 秒無響應
ANR 時,系統會生成一個 traces.txt 的文件放在 /data/anr/ 下。通過 adb 命令將其導出到本地
$adb pull data/anr/traces.txt ~/Desktop
UI 線程做耗時操作,內存泄露導致內存不足都可能產生 ANR。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。
新聞熱點
疑難解答