問題背景
在桌面轉屏發現響應不夠迅速,對比其他產品有很大的提升空間,針對此問題進行了一些分析和優化。
問題分析和解決方法
首先簡單介紹一下旋轉屏幕的流程,首先各個界面要進行重繪,在重繪過程中要進行凍屏,只有所有Window
都進行繪製完成了才進行轉屏,因此這裏面就有個木桶效應,轉屏的時間取決於重繪最慢的那個。
首先分析Log,找出可以優化的點:
adb shell dumpsys window -d enable 10
adb logcat -v threadtime -s WindowManager | grep -E "Screen frozen for|Dismissing screen|Orientation start waiting for draw|Orientation not waiting for draw"
adb shell dumpsys window -d enable 10
是使能DEBUG_ORIENTATION
,開啓打印轉屏相關的Log。
WindowManager: Orientation start waiting for draw mDrawState=DRAW_PENDING in Window{249e41f u0 StatusBar}, surface Surface(name=StatusBar)
WindowManager: Orientation start waiting for draw mDrawState=DRAW_PENDING in Window{731dc6a u0 com.android.launcher/com.android.launcher.Launcher}, surface Surface(name=com.android.launcher/com.android.launcher.Launcher)
WindowManager: Orientation start waiting for draw mDrawState=DRAW_PENDING in Window{b22eda5 u0 com.android.systemui.ImageWallpaper}, surface Surface(name=com.android.systemui.ImageWallpaper)
WindowManager: Orientation start waiting for draw mDrawState=DRAW_PENDING in Window{731dc6a u0 com.android.launcher/com.android.launcher.Launcher}, surface Surface(name=com.android.launcher/com.android.launcher.Launcher)
WindowManager: Orientation start waiting for draw mDrawState=DRAW_PENDING in Window{731dc6a u0 com.android.launcher/com.android.launcher.Launcher}, surface Surface(name=com.android.launcher/com.android.launcher.Launcher)
WindowManager: Orientation start waiting for draw mDrawState=DRAW_PENDING in Window{94517ed u0 com.android.launcher/com.android.launcher.Launcher}, surface Surface(name=com.android.launcher/com.android.launcher.Launcher)
WindowManager: Orientation not waiting for draw in Window{94517ed u0 com.android.launcher/com.android.launcher.Launcher}, surface Surface(name=com.android.launcher/com.android.launcher.Launcher)
WindowManager: Orientation not waiting for draw in Window{b22eda5 u0 com.android.systemui.ImageWallpaper}, surface Surface(name=com.android.systemui.ImageWallpaper)
WindowManager: Orientation not waiting for draw in Window{249e41f u0 StatusBar}, surface Surface(name=StatusBar)
WindowManager: Screen frozen for +968ms due to Window{249e41f u0 StatusBar}
WindowManager: **** Dismissing screen rotation animation
通過Log發現,轉屏是要等StatusBar
,Launcher
和ImageWallpaper
繪製完纔會開始的。
根據Screen frozen for +968ms due to Window{249e41f u0 StatusBar}
發現目前的瓶頸在狀態欄這裏,首先分析一下狀態欄的代碼,可以藉助於 TraceView 工具迅速定位到耗時較多方法的位置,發現在NotificationPanelView
的onConfigurationChanged
函數中有一項耗時的操作,先進行這部分優化。
然後看效果:
WindowManager: Screen frozen for +747ms due to Window{3aaa434 u0 com.android.launcher/com.android.launcher.Launcher}
發現這個時候瓶頸已經不再StatusBar
這裏了,接下面再優化Launcher
就可以。
接下來看看ImageWallpaper
是不是有優化的餘地呢?
通過 TraceView 工具發現在ImageWallpaper.drawFrame()
方法中,每次旋轉屏幕都會在updateWallpaperLocked()
中調用mWallpaperManager.getBitmap()
進行解碼圖片,這個也是沒有必要的,只初始化一次就可以了,可以進行如下的修改:
// Load bitmap if it is not yet loaded or if it was loaded at a different size
if (mBackground == null/* || surfaceDimensionsChanged*/) {
只在mBackground
爲null
是加在壁紙圖片。
第三步的任務就是優化Launcher
了,此處的優化點各不相同,而且較多,就不一一介紹了。