日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

一個(gè) Android 應(yīng)用是否流暢,或者說是否存在卡頓、丟幀現(xiàn)象,都與 60fps 和 16ms 有關(guān)。那么這兩個(gè)值是怎么來的呢?為什么以這兩個(gè)值為衡量標(biāo)準(zhǔn)呢?本文主要討論下渲染性能方面決定 Android 應(yīng)用流暢性的因素。

  • 12fps(幀/秒)

由于人類眼睛的特殊生理結(jié)構(gòu),如果所看畫面之幀率高于每秒約 10 - 12fps 的時(shí)候,就會認(rèn)為是連貫的。早期的無聲電影的幀率介于 16 - 24fps 之間,雖然幀率足以讓人感覺到運(yùn)動(dòng),但往往被認(rèn)為是在快放幻燈片。在 1920 年代中后期,無聲電影的幀率提高到 20 - 26fps 之間。

  • 24fps

1926 年有聲電影推出,人耳對音頻的變化更敏感,反而削弱了人對電影幀率的關(guān)注。因?yàn)樵S多無聲電影使用 20 - 26fps 播放,所以選擇了中間值 24fps 作為有聲電影的幀率。之后 24fps 成為 35mm 有聲電影的標(biāo)準(zhǔn)。

  • 30fps

早期的高動(dòng)態(tài)電子游戲,幀率少于每秒 30fps 的話就會顯得不連貫。這是因?yàn)闆]有動(dòng)態(tài)模糊使流暢度降低。(注:如果需要了解動(dòng)態(tài)模糊技術(shù)相關(guān)知識,可以查閱 這里)

  • 60fps

在實(shí)際體驗(yàn)中,60fps 相對于 30fps 有著更好的體驗(yàn)。

  • 85fps

一般而言,大腦處理視頻的極限。

所以,總體而言,幀率越高體驗(yàn)越好。一般的電影拍攝及播放幀率均為每秒 24 幀,但是據(jù)稱《霍比特人:意外旅程》是第一部以每秒 48 幀拍攝及播放的電影,觀眾認(rèn)為其逼真度得到了顯著的提示。

目前,大多數(shù)顯示器根據(jù)其設(shè)定按 30Hz、 60Hz、 120Hz 或者 144Hz 的頻率進(jìn)行刷新。而其中最常見的刷新頻率是 60Hz。

這樣做是為了繼承以前電視機(jī)刷新頻率為 60Hz 的設(shè)定。而 60Hz 是美國交流電的頻率,電視機(jī)如果匹配交流電的刷新頻率就可以有效的預(yù)防屏幕中出現(xiàn)滾動(dòng)條,即互調(diào)失真。

16 ms

正如上面所述目前大多數(shù)顯示器的刷新率是 60Hz,Android 設(shè)備的刷新率也是 60Hz。只有當(dāng)畫面達(dá)到 60fps 時(shí) App 應(yīng)用才不會讓用戶感覺到卡頓。那么 60fps 也就意味著 1000ms/60Hz = 16ms。也就是說 16ms 渲染一次畫面才不會卡頓。

CPU vs GPU

渲染操作通常依賴于兩個(gè)核心組件:CPU 與 GPU。CPU 負(fù)責(zé)包括 Measure、Layout、Record、Execute 的計(jì)算操作,GPU 負(fù)責(zé) Rasterization (柵格化)操作。

CPU 通常存在的問題的原因是存在非必需的視圖組件,它不僅僅會帶來重復(fù)的計(jì)算操作,而且還會占用額外的 GPU 資源。

找出卡頓的元兇——渲染性能優(yōu)化

 

CPU vs GPU

Android UI 與 GPU

了解 Android 是如何利用 GPU 進(jìn)行畫面渲染有助于我們更好的理解性能問題。

那么一個(gè)最實(shí)際的問題是:Activity 的畫面是如何繪制到屏幕上的?那些復(fù)雜的 XML 布局文件又是如何能夠被識別并繪制出來的?

找出卡頓的元兇——渲染性能優(yōu)化

 

Resterization 柵格化是繪制那些 Button、Shape、Path、String、Bitmap 等組件最基礎(chǔ)的操作。它把那些組件拆分到不同的像素上進(jìn)行顯示。

這是一個(gè)很費(fèi)時(shí)的操作,GPU 的引入就是為了加快柵格化的操作。

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

找出卡頓的元兇——渲染性能優(yōu)化

 

CPU 與 GPU 工作流程

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

在 Android 里面那些由主題所提供的資源(例如:Bitmaps、Drawables)都是一起打包到統(tǒng)一的 Texture 紋理當(dāng)中,然后再傳遞到GPU里面,這意味著每次你需要使用這些資源的時(shí)候,都是直接從紋理里面進(jìn)行獲取渲染的。

當(dāng)然,隨著 UI 組件的越來越豐富,有了更多演變的形態(tài)。例如,顯示圖片的時(shí)候,需要先經(jīng)過 CPU 的計(jì)算加載到內(nèi)存中,然后傳遞給 GPU 進(jìn)行渲染。文字的顯示更加復(fù)雜,需要先經(jīng)過 CPU 換算成紋理,然后再交給 GPU 進(jìn)行渲染,回到 CPU 繪制單個(gè)字符的時(shí)候,再重新引用經(jīng)過 GPU 渲染的內(nèi)容。動(dòng)畫則是一個(gè)更加復(fù)雜的操作流程。

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

UI 組件的更新

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

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

如果你在后續(xù)有執(zhí)行類似移動(dòng)這個(gè) View 的位置等操作而需要再次渲染這個(gè) View 時(shí),我們就僅僅需要額外操作一次渲染指令就夠了。然而如果你修改了 View 中的某些可見組件,那么之前的 DisplayList 就無法繼續(xù)使用了,我們需要回頭重新創(chuàng)建一個(gè) DisplayList 并且重新執(zhí)行渲染指令并更新到屏幕上。

需要注意的是:任何時(shí)候 View 中的繪制內(nèi)容發(fā)生變化時(shí),都會重新執(zhí)行創(chuàng)建 DisplayList,渲染 DisplayList,更新到屏幕上等一系列操作。這個(gè)流程的表現(xiàn)性能取決于你的 View 的復(fù)雜程度,View 的狀態(tài)變化以及渲染管道的執(zhí)行性能。

找出卡頓的元兇——渲染性能優(yōu)化

 

UI 組件的更新

舉個(gè)例子,假設(shè)某個(gè) Button 的大小需要增大到目前的兩倍,在增大 Button 大小之前,需要通過父 View 重新計(jì)算并擺放其他子 View 的位置。修改 View 的大小會觸發(fā)整個(gè) HierarcyView 的重新計(jì)算大小的操作。如果是修改 View 的位置則會觸發(fā) HierarchView 重新計(jì)算其他 View 的位置。如果布局很復(fù)雜,這就會很容易導(dǎo)致嚴(yán)重的性能問題。

垂直同步

為了理解 App 是如何進(jìn)行渲染的,我們必須了解手機(jī)硬件是如何工作,那么就必須理解什么是垂直同步(VSYNC)。

在講解 VSYNC 之前,我們需要了解兩個(gè)相關(guān)的概念:

刷新率

刷新率(Refresh Rate)代表了屏幕在一秒內(nèi)刷新屏幕的次數(shù),這取決于硬件的固定參數(shù),例如 60Hz。

幀率

幀率(Frame Rate)代表了 GPU 在一秒內(nèi)繪制操作的幀數(shù),例如 30fps,60fps。

GPU 會獲取圖形數(shù)據(jù)進(jìn)行渲染,然后硬件負(fù)責(zé)把渲染后的內(nèi)容呈現(xiàn)到屏幕上,他們兩者不停的進(jìn)行協(xié)作。

找出卡頓的元兇——渲染性能優(yōu)化

 

GPU 渲染

玩游戲的同學(xué),尤其是大型 FPS 游戲應(yīng)該都見過「垂直同步」這個(gè)選項(xiàng)。因?yàn)?GPU 的生成圖像的頻率與顯示器的刷新頻率是相互獨(dú)立的,所以就涉及到了一個(gè)配合的問題。

最理想的情況是兩者之間的頻率是相同且協(xié)同進(jìn)行工作的,在這樣的理想條件下,達(dá)到了最優(yōu)解。

找出卡頓的元兇——渲染性能優(yōu)化

 

GPU 幀率

但實(shí)際中 GPU 的生成圖像的頻率是變化的,如果沒有有效的技術(shù)手段進(jìn)行保證,兩者之間很容易出現(xiàn)這樣的情況。

當(dāng) GPU 還在渲染下一幀圖像時(shí),顯示器卻已經(jīng)開始進(jìn)行繪制,這樣就會導(dǎo)致屏幕撕裂(Tear)。這會使得屏幕的一部分顯示的是前一幀的內(nèi)容,而另一部分卻在顯示下一幀的內(nèi)容。如下圖所示:

找出卡頓的元兇——渲染性能優(yōu)化

 

撕裂的圖像

屏幕撕裂(Tear)的問題,早在 PC 游戲時(shí)代就被發(fā)現(xiàn), 并不停的在嘗試進(jìn)行解決。其中最知名可能也是最古老的解決方案就是 VSYNC 技術(shù)。

VSYNC 的原理簡單而直觀:產(chǎn)生屏幕撕裂的原因是 GPU 在屏幕刷新時(shí)進(jìn)行了渲染,而 VSYNC 通過同步渲染/刷新時(shí)間的方式來解決這個(gè)問題。

顯示器的刷新頻率為 60Hz,若此時(shí)開啟 VSYNC,將控制 GPU 渲染速度在 60Hz 以內(nèi)以匹配顯示器刷新頻率。這也意味著,在 VSYNC 的限制下,GPU 顯示性能的極限就限制為 60Hz 以內(nèi)。這樣就能很好的避免圖像撕裂的問題。

通常來說,幀率超過刷新頻率只是一種理想的狀況,在超過 60fps 的情況下,GPU 所產(chǎn)生的幀數(shù)據(jù)會因?yàn)榈却?VSYNC 的刷新信息而被 Hold 住,這樣能夠保持每次刷新都有實(shí)際的新的數(shù)據(jù)可以顯示。但是我們遇到更多的情況是幀率小于刷新頻率。

找出卡頓的元兇——渲染性能優(yōu)化

 

VSYNC

在這種情況下,某些幀顯示的畫面內(nèi)容就會與上一幀的畫面相同。糟糕的事情是,幀率從超過 60fps 突然掉到 60fps 以下,這樣就會發(fā)生 LAG、JANK、HITCHING 等卡頓掉幀的不順滑的情況。這也是用戶感受不好的原因所在。

渲染性能

大多數(shù)用戶感知到的卡頓等性能問題的最主要根源都是因?yàn)殇秩拘阅埽≧endering Performance)。

從設(shè)計(jì)師的角度,他們希望 App 能夠有更多的動(dòng)畫,圖片等時(shí)尚元素來實(shí)現(xiàn)流暢的用戶體驗(yàn)。但是 Android 系統(tǒng)很有可能無法及時(shí)完成那些復(fù)雜的界面渲染操作。

Android 系統(tǒng)每隔 16ms 發(fā)出 VSYNC 信號,觸發(fā)對 UI 進(jìn)行渲染,如果每次渲染都成功,這樣就能夠達(dá)到流暢的畫面所需要的 60fps,為了能夠?qū)崿F(xiàn) 60fps,這意味著程序的大多數(shù)操作都必須在 16ms 內(nèi)完成。

找出卡頓的元兇——渲染性能優(yōu)化

 

VSYNC 信號

如果你的某個(gè)操作花費(fèi)時(shí)間是 24ms,系統(tǒng)在得到 VSYNC 信號的時(shí)候就無法進(jìn)行正常渲染,這樣就發(fā)生了丟幀現(xiàn)象。那么用戶在 32ms 內(nèi)看到的會是同一幀畫面。

找出卡頓的元兇——渲染性能優(yōu)化

 

丟幀

用戶容易在 UI 執(zhí)行動(dòng)畫或者滑動(dòng) ListView 的時(shí)候感知到卡頓不流暢,是因?yàn)檫@里的操作相對復(fù)雜,容易發(fā)生丟幀的現(xiàn)象,從而感覺卡頓。

有很多原因可以導(dǎo)致丟幀,也許是因?yàn)槟愕?layout 太過復(fù)雜,無法在 16ms 內(nèi)完成渲染,有可能是因?yàn)槟愕?UI 上有層疊太多的繪制單元,還有可能是因?yàn)閯?dòng)畫執(zhí)行的次數(shù)過多。這些都會導(dǎo)致 CPU 或者 GPU 負(fù)載過重。

過度重繪

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

找出卡頓的元兇——渲染性能優(yōu)化

 

Overdraw

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

如何找出過度重繪?

很榮幸 Android 系統(tǒng)的開發(fā)者模式中,提供了一些工具可以幫助我們找出過度重繪。

首先,打開手機(jī)里面的開發(fā)者選項(xiàng)(這個(gè)都找不到,那還開發(fā)什么 Android?),可以找到下面幾個(gè)選項(xiàng):

調(diào)試 GPU 過度重繪(Debug GPU overdraw)

我們可以通過手機(jī)設(shè)置里面的 開發(fā)者選項(xiàng) ,打開 顯示過渡繪制區(qū)域(Show GPU Overdraw)的選項(xiàng),可以觀察 UI 上的 Overdraw 情況。

找出卡頓的元兇——渲染性能優(yōu)化

 

Debug GPU overdraw

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

  • 真彩色:沒有過度繪制
  • 藍(lán)色:過度重繪 1 次

像素繪制了 2 次。大片的藍(lán)色還是可以接受的(若整個(gè)窗口是藍(lán)色的,可以擺脫一層)。

  • 綠色:過度重繪 2 次

像素繪制了 3 次。中等大小的綠色區(qū)域是可以接受的但你應(yīng)該嘗試優(yōu)化、減少它們。

  • 淡紅:過度重繪 3 次

像素繪制了 4 次,小范圍可以接受。

  • 深紅:過度重繪 4 次或更多

像素繪制了 5 次或者更多。這是錯(cuò)誤的,要修復(fù)它們。

Overdraw 有時(shí)候是因?yàn)槟愕腢I布局存在大量重疊的部分,還有的時(shí)候是因?yàn)榉潜仨毜闹丿B背景。

例如:某個(gè) Activity 有一個(gè)背景,然后里面的 Layout 又有自己的背景,同時(shí)子 View 又分別有自己的背景。僅僅是通過移除非必須的背景圖片,這就能夠減少大量的紅色 Overdraw 區(qū)域,增加藍(lán)色區(qū)域的占比。這一措施能夠顯著提升程序性能。

找出卡頓的元兇——渲染性能優(yōu)化

 

優(yōu)化過度重繪

GPU 呈現(xiàn)模式分析(Profile GPU Rendering)

我們可以通過手機(jī)設(shè)置里面的 開發(fā)者選項(xiàng) 中找到 GPU 呈現(xiàn)模式分析(Peofile GPU Rendering tool) ,然后選擇 在屏幕上顯示為條形圖(On screen as bars)。

找出卡頓的元兇——渲染性能優(yōu)化

 

Profile GPU Rendering

在 Android 系統(tǒng)中是以 60fps 為滿幀,綠色橫線為 16ms 分界線,低于綠線即為流暢。

屏幕下方的柱狀圖每一根代表一幀,其高度表示「渲染這一幀耗時(shí)」,隨著手機(jī)屏幕界面的變化,柱狀圖會持續(xù)刷新每幀用時(shí)的具體情況(通過高度表示)。

那么,當(dāng)柱狀圖高于綠線,是不是就說明我卡了呢?其實(shí)這不完全正確,這里就要開始分析組成每一根柱狀圖不同顏色所代表的含義了。

找出卡頓的元兇——渲染性能優(yōu)化

 

gpu 16ms

  • 紅色

代表了「執(zhí)行時(shí)間」,它指的是 Android 渲染引擎執(zhí)行盒子中這些繪制命令的時(shí)間。

假如當(dāng)前界面的視圖越多,那么紅色便會「跳」得越高。實(shí)際使用中,比如我們平時(shí)刷淘寶 App 時(shí)遇到出現(xiàn)多張縮略圖需要加載時(shí),那么紅色會突然跳很高,但是此時(shí)你的頁面滑動(dòng)其實(shí)是流暢的,雖然等了零點(diǎn)幾秒圖片才加載出來,但其實(shí)這可能并不意味著你卡住了。

  • 黃色

通常較短,它代表著 CPU 通知 GPU 你已經(jīng)完成視圖渲染了,不過在這里 CPU 會等待 GPU 的回話,當(dāng) GPU 說「好的知道了」,才算完事兒。

假如橙色部分很高的話,說明當(dāng)前 GPU 過于忙碌,有很多命令需要去處理,比如 Android 淘寶客戶端,紅色黃色通常會很高。

  • 藍(lán)色

假如想通過玄學(xué)曲線來判斷流暢度的話,其實(shí)藍(lán)色的參考意義是較大的。藍(lán)色代表了視圖繪制所花費(fèi)的時(shí)間,表示視圖在界面發(fā)生變化(更新)的用時(shí)情況。

當(dāng)它越短時(shí),即便是體驗(yàn)上更接近「絲滑」,當(dāng)他越長時(shí),說明當(dāng)前視圖較復(fù)雜或者無效需要重繪,即我們通常說的「卡了」。

理解了玄學(xué)曲線不同顏色代表的意義,看懂玄學(xué)曲線就不難了。一般情況下,當(dāng)藍(lán)色低于綠線時(shí)都不會出現(xiàn)卡頓,但是想要追求真正的絲般順滑那當(dāng)然還是三色全部處于綠線以下最為理想。

Hierarchy Viewer

Hierarchy Viewer 是 Android Device Monitor 中的一個(gè)工具,它可以幫助我們檢測布局層次結(jié)構(gòu)中每個(gè)視圖的布局速度。

它的界面如下:

找出卡頓的元兇——渲染性能優(yōu)化

 

Hierarchy Viewer

有一定開發(fā)經(jīng)驗(yàn)的小伙伴應(yīng)該使用過它,不過現(xiàn)在已經(jīng)被「棄用了」,google 推薦我們使用 Layout Inspector 來檢查應(yīng)用程序的視圖層次結(jié)構(gòu)。

Layout Inspector

Layout Inspector 集成在 Android Studio 中,點(diǎn)擊 Tools > Layout Inspector,在出現(xiàn)的Choose Process 對話框中,選擇您想要檢查的應(yīng)用進(jìn)程,然后點(diǎn)擊 OK

找出卡頓的元兇——渲染性能優(yōu)化

 

Layout Inspector

默認(rèn)情況下,Choose Process 對話框僅會為 Android Studio 中當(dāng)前打開的項(xiàng)目列出進(jìn)程,并且該項(xiàng)目必須在設(shè)備上運(yùn)行。

如果您想要檢查設(shè)備上的其他應(yīng)用,請點(diǎn)擊 Show all processes。如果您正在使用已取得 root 權(quán)限的設(shè)備或者沒有安裝 Google Play 商店的模擬器,那么您會看到所有正在運(yùn)行的應(yīng)用。否則,您只能看到可以調(diào)試的運(yùn)行中應(yīng)用。

布局檢查器會捕獲快照,將它保存為 .li 文件并打開。如圖下圖所示,布局檢查器將顯示以下內(nèi)容:

找出卡頓的元兇——渲染性能優(yōu)化

 

Layout Inspector

優(yōu)化布局

使用上面的工具找到了過度重繪的地方,就需要優(yōu)化自己的代碼,我們可以通過下面幾個(gè)方式進(jìn)行優(yōu)化。

include

include 標(biāo)簽常用于將布局中的公共部分提取出來供其他 layout 共用,以實(shí)現(xiàn)布局模塊化。

merge

merge 標(biāo)簽主要用于輔助 include 標(biāo)簽,在使用 include 后可能導(dǎo)致布局嵌套過多,多余的 layout 節(jié)點(diǎn)或?qū)е陆馕鲎兟?/p>

例如:根布局是 Linearlayout,那么我們又 include 一個(gè) LinerLayout 布局就沒意義了,反而會減慢 UI 加載速度。

ViewStub

ViewStub 標(biāo)簽最大的優(yōu)點(diǎn)是當(dāng)你需要時(shí)才會加載,使用它并不會影響UI初始化時(shí)的性能。

例如:不常用的布局像進(jìn)度條、顯示錯(cuò)誤消息等可以使用 ViewStub 標(biāo)簽,以減少內(nèi)存使用量,加快渲染速度.。

ViewStub 是一個(gè)不可見的,實(shí)際上是把寬高設(shè)置為 0 的 View。效果有點(diǎn)類似普通的 view.setVisible(),但性能體驗(yàn)提高不少。

ConstraintLayout

約束布局 ConstraintLayout 是一個(gè) ViewGroup,可以在 API 9 以上的 Android 系統(tǒng)使用它,它的出現(xiàn)主要是為了解決布局嵌套過多的問題,以靈活的方式定位和調(diào)整小部件。從 Android Studio 2.3 起,官方的模板默認(rèn)使用 ConstraintLayout。

更多使用細(xì)節(jié)詳見:Android 開發(fā)文檔 - ConstraintLayout、ConstraintLayout,看完一篇真的就夠了么?。

優(yōu)化自定義 View

onDraw()

減少 onDraw() 耗時(shí)操作。

clipRect() 與 quickReject()

我們可以通過 canvas.clipRect() 來幫助系統(tǒng)識別那些可見的區(qū)域。這個(gè)方法可以指定一塊矩形區(qū)域,只有在這個(gè)區(qū)域內(nèi)才會被繪制,其他的區(qū)域會被忽視。

這個(gè)API可以很好的幫助那些有多組重疊組件的自定義 View 來控制顯示的區(qū)域。同時(shí) clipRect 方法還可以幫助節(jié)約 CPU 與 GPU 資源,在 clipRect 區(qū)域之外的繪制指令都不會被執(zhí)行,那些部分內(nèi)容在矩形區(qū)域內(nèi)的組件,仍然會得到繪制。

找出卡頓的元兇——渲染性能優(yōu)化

 

clipRect

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

找出卡頓的元兇——渲染性能優(yōu)化

 

quickReject

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

protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 
 if (mDroids.length > 0 && mDroidCards.size() == mDroids.length) {
 // 過度重繪代碼
 int i;
 for (i = 0; i < mDroidCards.size(); i++) {
 // 每張卡片都放在前一張卡片的右側(cè)
 mCardLeft = i * mCardSpacing;
 drawDroidCard(canvas, mDroidCards.get(i), mCardLeft, 0);
 }
 }

 invalidate();
}

打開「開發(fā)者選項(xiàng)」中的「顯示過度渲染」,可以看到我們這個(gè)自定義的 View 部分區(qū)域存在著過度繪制。

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

protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);

 if (mDroids.length > 0 && mDroidCards.size() == mDroids.length) {
 int i;
 for (i = 0; i < mDroidCards.size() - 1; i++) {
 // 每張卡片都放在前一張卡片的右側(cè)
 mCardLeft = i * mCardSpacing;
 // 保存 canvas 的狀態(tài)
 canvas.save();
 // 將繪圖區(qū)域限制為可見的區(qū)域
 canvas.clipRect(mCardLeft, 0, mCardLeft + mCardSpacing,
 mDroidCards.get(i).getHeight());

 drawDroidCard(canvas, mDroidCards.get(i), mCardLeft, 0);
 // 將畫布恢復(fù)到非剪切狀態(tài)
 canvas.restore();
 }

 // 繪制最后沒有剪裁的卡片
 drawDroidCard(canvas, mDroidCards.get(i),
 mCardLeft + mCardSpacing, 0);
 }

 invalidate();
}

避免使用不支持硬件加速的 API

Android 系統(tǒng)中圖形繪制分為兩種方式,純軟件繪制和使用硬件加速繪制。

大家可以查看 美團(tuán)技術(shù)團(tuán)隊(duì) - Android 硬件加速原理與實(shí)現(xiàn)簡介 這篇文章了解下硬件加速的實(shí)現(xiàn)原理。

簡單來說在 Android 3.0(API 11)之前沒有硬件加速,圖形繪制是純軟件的方式,DisplayList 的生成和繪制都需要 CPU 來完成。之后加入的硬件加速(默認(rèn)開啟)將一部分圖形相關(guān)的操作交給 GPU 來處理,這樣大大減少了 CPU 的運(yùn)算壓力。

今年金九銀十我花一個(gè)月的時(shí)間收錄整理了一套知識體系,如果有想法深入的系統(tǒng)化的去學(xué)習(xí)的,可以私信我【安卓】,我會把我收錄整理的資料都送給大家,幫助大家更快的進(jìn)階。

分享到:
標(biāo)簽:Android
用戶無頭像

網(wǎng)友整理

注冊時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定