自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Android性能優(yōu)化之渲染篇

移動開發(fā) Android
Google近期在Udacity上發(fā)布了Android性能優(yōu)化的在線課程,分別從渲染,運算與內(nèi)存,電量幾個方面介紹了如何去優(yōu)化性能,這些課程是Google之前在Youtube上發(fā)布的Android性能優(yōu)化典范專題課程的細(xì)化與補充。

Google近期在Udacity上發(fā)布了Android性能優(yōu)化的在線課程,分別從渲染,運算與內(nèi)存,電量幾個方面介紹了如何去優(yōu)化性能,這些課程是Google之前在Youtube上發(fā)布的Android性能優(yōu)化典范專題課程的細(xì)化與補充。

下面是渲染篇章的學(xué)習(xí)筆記,部分內(nèi)容和前面的性能優(yōu)化典范有重合,歡迎大家一起學(xué)習(xí)交流!

 

1)Why Rendering Performance Matters

 

現(xiàn)在有不少App為了達(dá)到很華麗的視覺效果,會需要在界面上層疊很多的視圖組件,但是這會很容易引起性能問題。如何平衡Design與Performance就很需要智慧了。

 

2)Defining ‘Jank’

 

大多數(shù)手機的屏幕刷新頻率是60hz,如果在1000/60=16.67ms內(nèi)沒有辦法把這一幀的任務(wù)執(zhí)行完畢,就會發(fā)生丟幀的現(xiàn)象。丟幀越多,用戶感受到的卡頓情況就越嚴(yán)重。

 

3)Rendering Pipeline: Common Problems

渲染操作通常依賴于兩個核心組件:CPU與GPU。CPU負(fù)責(zé)包括Measure,Layout,Record,Execute的計算操作,GPU負(fù)責(zé)Rasterization(柵格化)操作。CPU通常存在的問題的原因是存在非必需的視圖組件,它不僅僅會帶來重復(fù)的計算操作,而且還會占用額外的GPU資源。

4)Android UI and the GPU

了解Android是如何利用GPU進(jìn)行畫面渲染有助于我們更好的理解性能問題。一個很直接的問題是:activity的畫面是如何繪制到屏幕上的?那些復(fù)雜的XML布局文件又是如何能夠被識別并繪制出來的?

Resterization柵格化是繪制那些Button,Shape,Path,String,Bitmap等組件最基礎(chǔ)的操作。它把那些組件拆分到不同的像素上進(jìn)行顯示。這是一個很費時的操作,GPU的引入就是為了加快柵格化的操作。

CPU負(fù)責(zé)把UI組件計算成Polygons,Texture紋理,然后交給GPU進(jìn)行柵格化渲染。

然而每次從CPU轉(zhuǎn)移到GPU是一件很麻煩的事情,所幸的是OpenGL ES可以把那些需要渲染的紋理Hold在GPU Memory里面,在下次需要渲染的時候直接進(jìn)行操作。所以如果你更新了GPU所hold住的紋理內(nèi)容,那么之前保存的狀態(tài)就丟失了。

在Android里面那些由主題所提供的資源,例如Bitmaps,Drawables都是一起打包到統(tǒng)一的Texture紋理當(dāng)中,然后再傳遞到GPU里面,這意味著每次你需要使用這些資源的時候,都是直接從紋理里面進(jìn)行獲取渲染的。當(dāng)然隨著UI組件的越來越豐富,有了更多演變的形態(tài)。例如顯示圖片的時候,需要先經(jīng)過CPU的計算加載到內(nèi)存中,然后傳遞給GPU進(jìn)行渲染。文字的顯示比較復(fù)雜,需要先經(jīng)過CPU換算成紋理,然后交給GPU進(jìn)行渲染,返回到CPU繪制單個字符的時候,再重新引用經(jīng)過GPU渲染的內(nèi)容。動畫則存在一個更加復(fù)雜的操作流程。

為了能夠使得App流暢,我們需要在每幀16ms以內(nèi)處理完所有的CPU與GPU的計算,繪制,渲染等等操作。

 

5)GPU Problem: Overdraw

 

Overdraw(過度繪制)描述的是屏幕上的某個像素在同一幀的時間內(nèi)被繪制了多次。在多層次重疊的UI結(jié)構(gòu)里面,如果不可見的UI也在做繪制的操作,會導(dǎo)致某些像素區(qū)域被繪制了多次。這樣就會浪費大量的CPU以及GPU資源。

當(dāng)設(shè)計上追求更華麗的視覺效果的時候,我們就容易陷入采用復(fù)雜的多層次重疊視圖來實現(xiàn)這種視覺效果的怪圈。這很容易導(dǎo)致大量的性能問題,為了獲得***的性能,我們必須盡量減少Overdraw的情況發(fā)生。

幸運的是,我們可以通過手機設(shè)置里面的開發(fā)者選項,打開Show GPU Overdraw的選項,觀察UI上的Overdraw情況。

藍(lán)色,淡綠,淡紅,深紅代表了4種不同程度的Overdraw情況,我們的目標(biāo)就是盡量減少紅色Overdraw,看到更多的藍(lán)色區(qū)域。

 

6)Visualize and Fix Overdraw - Quiz & Solution

 

這里舉了一個例子,通過XML文件可以看到有好幾處非必需的background。通過把XML中非必需的background移除之后,可以顯著減少布局的過度繪制。其中一個比較有意思的地方是:針對ListView中的Avatar ImageView的設(shè)置,在getView的代碼里面,判斷是否獲取到對應(yīng)的Bitmap,在獲取到Avatar的圖像之后,把ImageView的Background設(shè)置為Transparent,只有當(dāng)圖像沒有獲取到的時候才設(shè)置對應(yīng)的Background占位圖片,這樣可以避免因為給Avatar設(shè)置背景圖而導(dǎo)致的過度渲染。

總結(jié)一下,優(yōu)化步驟如下:

移除Window默認(rèn)的Background

 

移除XML布局文件中非必需的Background

 

按需顯示占位背景圖片

 

7)ClipRect & QuickReject

前面有提到過,對不可見的UI組件進(jìn)行繪制更新會導(dǎo)致Overdraw。例如Nav Drawer從前置可見的Activity滑出之后,如果還繼續(xù)繪制那些在Nav Drawer里面不可見的UI組件,這就導(dǎo)致了Overdraw。為了解決這個問題,Android系統(tǒng)會通過避免繪制那些完全不可見的組件來盡量減少Overdraw。那些Nav Drawer里面不可見的View就不會被執(zhí)行浪費資源。

但是不幸的是,對于那些過于復(fù)雜的自定義的View(通常重寫了onDraw方法),Android系統(tǒng)無法檢測在onDraw里面具體會執(zhí)行什么操作,系統(tǒng)無法監(jiān)控并自動優(yōu)化,也就無法避免Overdraw了。但是我們可以通過canvas.clipRect()來幫助系統(tǒng)識別那些可見的區(qū)域。這個方法可以指定一塊矩形區(qū)域,只有在這個區(qū)域內(nèi)才會被繪制,其他的區(qū)域會被忽視。這個API可以很好的幫助那些有多組重疊組件的自定義View來控制顯示的區(qū)域。同時clipRect方法還可以幫助節(jié)約CPU與GPU資源,在clipRect區(qū)域之外的繪制指令都不會被執(zhí)行,那些部分內(nèi)容在矩形區(qū)域內(nèi)的組件,仍然會得到繪制。

除了clipRect方法之外,我們還可以使用canvas.quickreject()來判斷是否沒和某個矩形相交,從而跳過那些非矩形區(qū)域內(nèi)的繪制操作。

 

8)Apply clipRect and quickReject - Quiz & Solution

 

上面的示例圖中顯示了一個自定義的View,主要效果是呈現(xiàn)多張重疊的卡片。這個View的onDraw方法如下圖所示:

打開開發(fā)者選項中的顯示過度渲染,可以看到我們這個自定義的View部分區(qū)域存在著過度繪制。那么是什么原因?qū)е逻^度繪制的呢?

9)Fixing Overdraw with Canvas API

下面的代碼顯示了如何通過clipRect來解決自定義View的過度繪制,提高自定義View的繪制性能:

下面是優(yōu)化過后的效果:

10)Layouts, Invalidations and Perf

Android需要把XML布局文件轉(zhuǎn)換成GPU能夠識別并繪制的對象。這個操作是在DisplayList的幫助下完成的。DisplayList持有所有將要交給GPU繪制到屏幕上的數(shù)據(jù)信息。

在某個View***次需要被渲染時,Display List會因此被創(chuàng)建,當(dāng)這個View要顯示到屏幕上時,我們會執(zhí)行GPU的繪制指令來進(jìn)行渲染。

如果View的Property屬性發(fā)生了改變(例如移動位置),我們就僅僅需要Execute Display List就夠了。

 

然而如果你修改了View中的某些可見組件的內(nèi)容,那么之前的DisplayList就無法繼續(xù)使用了,我們需要重新創(chuàng)建一個DisplayList并重新執(zhí)行渲染指令更新到屏幕上。

 

請注意:任何時候View中的繪制內(nèi)容發(fā)生變化時,都會需要重新創(chuàng)建DisplayList,渲染DisplayList,更新到屏幕上等一系列操作。這個流程的表現(xiàn)性能取決于你的View的復(fù)雜程度,View的狀態(tài)變化以及渲染管道的執(zhí)行性能。舉個例子,假設(shè)某個Button的大小需要增大到目前的兩倍,在增大Button大小之前,需要通過父View重新計算并擺放其他子View的位置。修改View的大小會觸發(fā)整個HierarcyView的重新計算大小的操作。如果是修改View的位置則會觸發(fā)HierarchView重新計算其他View的位置。如果布局很復(fù)雜,這就會很容易導(dǎo)致嚴(yán)重的性能問題。

11)Hierarchy Viewer: Walkthrough

Hierarchy Viewer可以很直接的呈現(xiàn)布局的層次關(guān)系,視圖組件的各種屬性。 我們可以通過紅,黃,綠三種不同的顏色來區(qū)分布局的Measure,Layout,Executive的相對性能表現(xiàn)如何。

 

12)Nested Hierarchies and Performance

 

提升布局性能的關(guān)鍵點是盡量保持布局層級的扁平化,避免出現(xiàn)重復(fù)的嵌套布局。例如下面的例子,有2行顯示相同內(nèi)容的視圖,分別用兩種不同的寫法來實現(xiàn),他們有著不同的層級。

下圖顯示了使用2種不同的寫法,在Hierarchy Viewer上呈現(xiàn)出來的性能測試差異:

13)Optimizing Your Layout

下圖舉例演示了如何優(yōu)化ListItem的布局,通過RelativeLayout替代舊方案中的嵌套LinearLayout來優(yōu)化布局。

 

責(zé)任編輯:chenqingxiang 來源: 胡凱的博客
相關(guān)推薦

2015-09-16 15:48:55

Android性能優(yōu)化電量

2015-09-16 14:37:50

Android性能優(yōu)化運算

2023-04-10 11:18:38

前端性能優(yōu)化

2021-07-29 14:20:34

網(wǎng)絡(luò)優(yōu)化移動互聯(lián)網(wǎng)數(shù)據(jù)存儲

2015-09-16 15:21:23

Android性能優(yōu)化內(nèi)存

2013-02-20 14:32:37

Android開發(fā)性能

2019-12-13 10:25:08

Android性能優(yōu)化啟動優(yōu)化

2009-08-13 16:22:18

ASP.NET性能優(yōu)化

2020-06-11 13:03:04

性能優(yōu)化緩存

2009-08-13 15:49:18

ASP.NET性能優(yōu)化

2013-09-17 10:32:08

Android性能優(yōu)化數(shù)據(jù)庫

2023-11-18 19:46:07

GPU架構(gòu)

2022-12-12 09:01:13

2017-01-15 15:13:37

Android性能優(yōu)化優(yōu)化點

2019-09-25 08:03:21

Android加速Google

2017-12-23 14:38:41

Android編程開發(fā)優(yōu)化

2022-06-06 22:36:55

渲染性能CSS

2021-07-05 14:55:28

前端優(yōu)化圖片

2019-03-15 15:00:49

Webpack構(gòu)建速度前端

2024-02-20 19:53:57

網(wǎng)絡(luò)通信協(xié)議
點贊
收藏

51CTO技術(shù)棧公眾號