程序猿自古以來和產品汪就是一段悲慘的孽緣,經歷了千百年的風吹雨打,他們還是堅強的“在一起”,也許這就是“愛”,由恨生愛的“愛”,簡單愛的“愛”,羅密歐對朱麗葉的“愛”...
話說,那是一個沉悶而太陽高照的下午,產品汪坐在一個程序猿的旁邊,只見檯面上擺着各種道具,水果刀、砍柴刀...不對,是Macbook、鍵盤、鼠標,還有那臺27寸的顯示器...
程序猿抖着腳,深情的望着坐在旁邊的產品汪,而產品汪則手指着桌面上的一部殘破並且古老的Android手機。
故事,就這麼發生了...
2故事的開始
“不是,你到底想怎樣啊?需求和UI都按你說的做完了啊,現在還在嘰嘰歪歪的幹哈啊?!”程序猿飆出一段質問產品汪的話,產品汪沉穩的指着手機,“沒錯,是做完了,但是你看下這個界面,滑動一下,你不覺得頓卡頓卡的嗎?還有這個、那個...”,“這不挺好的嗎?你的需求完美的實現了啊,就要付出這樣的代價啦,還想怎樣啊?”程序猿抱怨着,“不行!一定要解決這個低端機卡頓的問題,不然這個用戶體驗太差了!”產品汪非常果斷而堅決的說。
程序猿心裏瞬間千萬只草泥馬飛奔而過,手握着桌面上的水果刀,額,不對,是鼠標...戴上耳機,噼裏啪啦啦的敲着鍵盤,開啓了改就改誰怕誰模式...但是心裏默唸着:小樣,小心有一天掉坑裏去了...
3故事的經過注:以下都是程序猿的個人秀和心理變化歷程,可能會引起某些人不適,但是還是堅持下去吧,sorry。
只見他打開最熟悉的開發工具Android Studio,把手機插上,“噔”,連接成功,打開親生孕育的APP,滑了兩下,確實是有點卡啊,怎麼剛開始就虛了啊。讓我好好瞧瞧。
打開對應的界面xml文件和代碼文件,一看,這是哪個傻*寫的代碼啊,ListView的convertView都沒複用,每次都重新繪製了一次,也沒用ViewHolder,這圖片加載也沒異步處理,而且還全加載了大圖,讓我再滑一下,滑動過程還繼續加載圖片啊,你當Android手機是超級計算器啊?!
不對,這好像是我自己寫的啊,當時因爲快下班了,急急忙忙就寫了,忘記優化了啊,被這該死的產品汪抓到把柄了!以後不管項目時間多趕都不能把代碼寫得那麼爛才行,來吧,趕緊優化一下吧...
嗯,這樣看起來就舒服多了嘛(圖片異步加載可使用第三方圖片加載庫如Glide,這裏就忽略了哈)。
來,跑上去看下。嗯...確實好了挺多了,咦,不對啊,怎麼感覺還是有點卡頓,該優化的我也優化了啊,還有哪呢?
是不是佈局層級太深了啊?讓我打開手機開發者設置裏的GPU過度繪製看下,我了個天,打開之後一片深紅深紅的...
注:
1、原色 – 沒有被過度繪製– 繪製了兩次。
2、藍色 – 1次過度繪製 – 繪製了兩次。
3、綠色 – 2次過度繪製 – 繪製了三次。
4、粉色 – 3次過度繪製 – 繪製了四次。
5、紅色 – 4次過度繪製 – 繪製了四次以上。
深呼吸...繼續吧,革命尚未成功,讓我想想有哪些可以優化的點呢?
佈局優化呢,要減少層級、減少測量和繪製時間,並且提高View的複用性。
要達到這幾點,可以通過如下方法:
合理使用RelativeLayout和LinerLayout,怎麼個合理使用呢?
RelativeLayout比LinearLayout慢,是因爲它會讓子View調用2次measure過程,而LinearLayout只需一次,但是有weight屬性存在時,LinearLayout也需要兩次measure;
RelativeLayout的子View如果高度和RelativeLayout不同,會導致RelativeLayout在onMeasure()方法中做橫向測量時,縱向的測量結果尚未完成,只好暫時使用自己的高度傳入子View系統。而父View給子View傳入的值也沒有變化就不會做無謂的測量的優化會失效,可以使用padding代替margin以優化;
在不響應層級深度的情況下,使用Linearlayout而不是RelativeLayout。
學會使用Merge,可以刪減多餘的層級,merge多用於替換FrameLayout或者當一個佈局包含另一個時,merge標籤消除視圖層次結構中多餘的視圖組。例如你的主佈局文件是垂直佈局,引入了一個垂直佈局的include,這是如果include佈局使用的LinearLayout就沒意義了,使用的話反而減慢你的UI表現。
使用 ViewStub,它是一個看不見的、不佔佈局位置、佔用資源非常小的視圖對象,提高顯示的速度。
ViewStub最大的優點是當你需要時纔會加載,使用他並不會影響UI初始化時的性能。各種不常用的佈局想進度條、顯示錯誤消息等可以使用ViewStub,以減少內存使用量,加快渲染速度。ViewStub是一個不可見的,大小爲0的View。
使用include標籤來提高View佈局的複用性。
儘可能少用wrap_content。wrap_content 會增加布局 measure 時計算成本,在已知寬高爲固定值時,不用wrap_content 。
刪除控件中無用的屬性。
還有就是界面的避免過度繪製。
移除 XML 中非必須的背景,移除 Window 默認的背景、按需顯示佔位背景圖片。
使用自定義View,使用 canvas.clipRect()來幫助系統識別那些可見的區域,只有在這個區域內纔會被繪製。
對了,還有要保持合理的一個刷界面的機制,避免頻繁的刷新,還應該儘量避免將其他處理放在主線程中,比如特別複雜的數據計算和網絡請求等。
想都想好了,是時候展示一波了啊!
不對,好像還差點啥的。
用什麼工具來分析呢?
NO.1 Profile GPU Rendering
在手機開發者模式下,有一個卡頓檢測工具叫做:Profile GPU Rendering,如圖:
它的功能特點如下:
一個圖形監測工具,能實時反應當前繪製的耗時;
橫軸表示時間,縱軸表示每一幀的耗時;
隨着時間推移,從左到右的刷新呈現;
提供一個標準的耗時,如果高於標準耗時,就表示當前這一幀丟失。
NO.2 TraceView
TraceView 是 Android SDK 自帶的工具,用來分析函數調用過程,可以對 Android 的應用程序以及 Framework 層的代碼進行性能分析。它是一個圖形化的工具,最終會產生一個圖表,用於對性能分析進行說明,可以分析到每一個方法的執行時間,其中可以統計出該方法調用次數和遞歸次數,實際時長等參數維度。
NO.3 Systrace UI 性能分析
Systrace 是 Android 4.1及以上版本提供的性能數據採樣和分析工具,它是通過系統的角度來返回一些信息。它可以幫助開發者收集 Android 關鍵子系統,如 surfaceflinger、WindowManagerService 等 Framework 部分關鍵模塊、服務、View系統等運行信息,從而幫助開發者更直觀地分析系統瓶頸,改進性能。Systrace 的功能包括跟蹤系統的 I/O 操作、內核工作隊列、CPU 負載等,在 UI 顯示性能分析上提供很好的數據,特別是在動畫播放不流暢、渲染卡等問題上。
NO.4 HierarchyViewer
HierarchyViewer工具可以查看當前界面的View的層級關係,使用它可以清晰明瞭的查看到當前界面有哪些View是多餘的,當然也要結合佈局XML文件來分析啦。
OJBK了,開始展現實力的時候到了!!!
優化過程會導致觀看的不適,所以忽略了啊,敬請原諒,不原諒也沒啥,就這麼着了,哈哈!
4故事的尾聲“我就說你可以嘛,你看,這不就流暢多了啊,之前還那麼多抱怨啊...”產品汪露出了他那鋒利的鋼牙,程序猿貌似感覺到了接下來肯定又沒啥好事發生了。
“來來來,咱們過來看看這個需求...”
To Be Continue...