解決View Layer圓角卡頓的問題

使用layer繪制圓角的時候回造成界面滑動的時候卡頓,主要是:

原理

上面拖慢幀率的原因其實都是Off-Screen Rendering(離屏渲染)的原因。離屏渲染是個好東西,但是頻繁發(fā)生離屏渲染是非常耗時的。

Off-Screen Rendering

離屏渲染,指的是GPU在當前屏幕緩沖區(qū)以外新開辟一個緩沖區(qū)進行渲染操作。由上面的一個結(jié)論視圖和圓角的大小對幀率并沒有什么卵影響,數(shù)量才是傷害的核心輸出啊??梢灾离x屏渲染耗時是發(fā)生在離屏這個動作上面,而不是渲染。為什么離屏這么耗時?原因主要有創(chuàng)建緩沖區(qū)和上下文切換。創(chuàng)建新的緩沖區(qū)代價都不算大,付出最大代價的是上下文切換。

上下文切換

上下文切換,不管是在GPU渲染過程中,還是一直所熟悉的進程切換,上下文切換在哪里都是一個相當耗時的操作。首先我要保存當前屏幕渲染環(huán)境,然后切換到一個新的繪制環(huán)境,申請繪制資源,初始化環(huán)境,然后開始一個繪制,繪制完畢后銷毀這個繪制環(huán)境,如需要切換到On-Screen Rendering或者再開始一個新的離屏渲染重復之前的操作。 下圖描述了一次mask的渲染操作。

一次mask發(fā)生了兩次離屏渲染和一次主屏渲染。即使忽略昂貴的上下文切換,一次mask需要渲染三次才能在屏幕上顯示,這已經(jīng)是普通視圖顯示3陪耗時,若再加上下文環(huán)境切換,一次mask就是普通渲染的30倍以上耗時操作。問我這個30倍以上這個數(shù)據(jù)怎么的出來的?當我在cell的UIImageView的實例增加到150個,并去掉圓角的時候,幀數(shù)才跌至28幀每秒。雖然不是甚準確,但至少反映mask這個耗時是無mask操作的耗時的數(shù)十倍的。

應(yīng)對

那么如何應(yīng)對這個問題呢?不要在滾動視圖使用cornerRadius或者mask。如果你非要作死怎么辦呢?那么這樣也可以拯救你:

self.layer.shouldRasterize=YES;

self.layer.rasterizationScale= [UIScreen mainScreen].scale;

比如我用collectionview做瀑布流,每一個item都是一個圓角照片,即使我們使用了collectionview的重用機制,也會出現(xiàn)卡頓現(xiàn)象(雖然在6s上不是很明顯),如果重用你都不用的的話,那么真的是沒法用了。但是你如果加上rasterization的話,就會好很多的,不信可以試一下,效果很明顯。

這樣大部分情況下可以馬上挽救你的幀數(shù)在55幀每秒以上。shouldRasterize = YES會使視圖渲染內(nèi)容被緩存起來,下次繪制的時候可以直接顯示緩存,當然要在視圖內(nèi)容不改變的情況下。

除了上面非要作死的人外,大家還是采取預(yù)先生成圓角圖片,并緩存起來這個方法才是比較好的手段。預(yù)處理圓角圖片可以在后臺處理,處理完畢后緩存起來,再在主線程顯示,這就避免了不必要的離屏渲染了。

另外也有在圖片上面覆蓋一個鏤空圓形圖片的方法可以實現(xiàn)圓形頭像效果,這個也是極為高效的方法。缺點就是對視圖的背景有要求,單色背景效果就最為理想。

總結(jié)

實現(xiàn)圓角cornerRadius要比mask高效很多。

Rasterize在大部分情況下極大減少GPU工作。在有空間的情況下,大部分情況下緩存總能幫到你,不是嗎?

后臺預(yù)處理圖片也能很簡單幫上你很大的忙。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容