網絡上有許多關於UI卡頓優化的解析,但大部分都是簡單的原理介紹,例子都比較簡單,每每是爲了驗證UI卡頓而硬造的,不能在實際場景中應用。android
本文結合大圖加載,與UI卡頓優化,向你們介紹UI卡頓優化的基本原理。git
UI卡頓的根本緣由是UI線程沒法在16ms內完成UI繪製。 下面以android大圖加載爲例,結合內存分析,systrace,TraceView等分析UI卡頓優化.github
方法一是鴻洋大神多年前寫的一種使用BitmapRegionDecoder分區域加載實現大圖加載的方法,詳情可見如下連接canvas
Android 高清加載巨圖方案 拒絕壓縮圖片markdown
源碼地址可見:自定義大圖加載--LagouBitmap網絡
方法二基於SubsamplingScaleImageView這個庫來實現大圖加載,他主要利用了切片來實現大圖加載,詳細原理介紹能夠見如下連接.oop
Android超長圖加載與subsampling scale image view實現分析 使用SubSamplingScaleImageView實現加載post
源碼實例可見:SubSamplingScaleImageView優化
分別使用兩種方式加載圖片,滑動後使用Profiler查看內存狀況spa
方法1 方法2
能夠看出方法一存在比較嚴重的內存抖動,方法二的內存較爲平緩 其緣由在於方法一在內存中建立了對象,致使對象頻繁建立與回收,形成內存抖動
protected void onDraw(Canvas canvas) {
Bitmap bm = mDecoder.decodeRegion(mRect, options); canvas.drawBitmap(bm, 0, 0, null); } 複製代碼
方法1
方法2
能夠看出,方法1存在掉幀狀況,即沒法在16ms內完成繪製工做,systraceView提示Long View#draw,即繪製時間過長 而方法2則不存在掉幀狀況,繪製均可以在16ms內完成
方法一具體是什麼問題致使了沒法在16ms內繪製完成,咱們須要在TraceView中詳細定位一下
在TraceView中相同顏色的色塊即表明一個方法的執行,能夠清晰的看出圖中主線程有個方法執行時間過長 點擊後在下方會展現出詳細的方法名,即BitmapRegionDecoder.decodeRegion方法 能夠看出這是個耗時操做,在onDraw中反覆調用decodeRegion方法便是掉幀的緣由
1.在單純使用BitmapRegionDecoder加載大圖時,因爲在onDraw中頻繁建立對象會形成內存抖動,在onDraw中反覆調用decodeRegion,這是個耗時操做,會致使掉幀
2.而在SubScaleSampleImageView中,將大圖切片,再判斷是否可見,若是可見則加入內存中,不然回收,減小了內存佔用與抖動 同時根據不一樣的縮放比例選擇合適的採樣率,進一步減小內存佔用 同時在子線程進行decodeRegion操做,解碼成功後回調至主線程,減小UI卡頓.