如何做一个流畅的UI 组内分享记录
前提 最近做了一次組內分享,這個 idea 來自去滬江的分享會聽到的,學到了一些,也分享給組內的小伙伴.
###什么是卡頓? 這件事要從RunLoop開始,RunLoop是一個60FPS[注1]的回調,也就是說每16.7ms繪制一次屏幕,也就是我們需要在這個時間內完成緩沖區創建,緩沖區內容的繪制這些是CPU的工作;然后把緩沖區交給GPU渲染,這里包括了多個View的拼接(Compositing),紋理的渲染(Texture)等等,最后Display到屏幕上。但是如果你在16.7ms內做的事情太多,導致CPU,GPU無法在指定時間內完成指定的工作,那么就會出現卡頓現象,也就是丟幀。 ####用戶能感受到的卡頓: 1.頁面的 FPS 降低,滑動時有困頓; 2.頁面卡死,無法響應; 3.主線程的 Runloop 執行了很久; ####可能是什么原因導致了卡頓: 1.死鎖:主線程拿到鎖 A, 需要鎖 B;子線程拿到鎖 B,需要鎖 A,相互等待導致死鎖; 2.搶鎖:主線程需要讀取 DB,子線程在插入數據. 3.主線程大量 IO. 4.主線程大量計算. 5.大量的UI、復雜的UI繪制.
###屏幕的成像原理
iOS的顯示系統是由 Vsync 脈沖信號驅動的, Vsync 脈沖信號由硬件時鐘生成,大約每秒鐘發出60次, iPhone 采用的雙緩沖,安卓在4.1之后是三緩沖.[注2] 通常來說,計算機系統中的 CPU,GPU, 顯示器的協同工作是: 1.CPU 計算好顯示內容提交到 GPU; 2.GPU 渲染完成后將渲染結果放入 Back Buffer(第一緩沖區); 3.然后等待顯示器發的垂直同步信號(VSync),Frame Buffer(第二緩沖區)copy 第一緩沖區的顯示內容 4.顯示屏經過數模轉換顯示出來. 所以要避免卡頓就要在16.7ms 內完成第一緩沖區的創建,所以我們所能做的優化絕大部分要在CPU,GPU這兩部分. ###如何使頁面流暢 ####從CPU入手: 先看看CPU要做的事情: 1.對象創建; 2.布局計算; 3.復雜算法; 4.AutoLayout; 5.文本圖片的繪制; 這僅僅是列出一小部分CPU的工作,可以嘗試如何從以上幾條來優化: 1.對象創建:對象的創建會分配內存、調整屬性、文件的 IO等操作,這些都比較占 CPU的資源,如果一個 對象的創建會分配內存、調整屬性、甚至還有讀取文件等操作####從GPU入手: GPU的職責:根據CPU提供的內容進行渲染,輸出到屏幕上. 在 Core Animation的組成部分中, OpenGL ES 是直接調用 GPU 進行渲染的.它有兩種渲染方式:
- On-Screen Rendering
- Off-Screen Rendering:是指GPU在當前屏幕緩沖區以外新開辟一個緩沖區進行渲染操作.
#####為什么離屏渲染會帶來性能消耗? 1.創建新的緩沖區 2.多次上下文切換 #####離屏渲染的觸發方式 1.光柵化(shouldRasterize)[注3] 2.遮罩(masks) 3.陰影(shadows) 4.不透明(opacity) 5.圓角
###更多可優化點:
- 異步繪制
- 算法優化
- AsyncDisplayKit
- ...
###參考文檔
- 滬江技術沙龍的一篇 session
- ibireme的 blog
###Q&A
###注: 注1.FPS是圖像領域中的定義,是指畫面每秒傳輸幀數,通俗來講就是指動畫或視頻的畫面數。FPS是測量用于保存、顯示動態視頻的信息數量。每秒鐘幀數愈多,所顯示的動作就會愈流暢
注2.通常來說,計算機系統中 CPU、GPU、顯示器是以上面這種方式協同工作的。CPU 計算好顯示內容提交到 GPU,GPU 渲染完成后將渲染結果放入幀緩沖區,隨后視頻控制器會按照 VSync 信號逐行讀取幀緩沖區的數據,經過可能的數模轉換傳遞給顯示器顯示
注3..當一個列表視圖中出現大量圓角的 CALayer,并且快速滑動時,可以觀察到 GPU 資源已經占滿,而 CPU 資源消耗很少。這時界面仍然能正?;瑒?#xff0c;但平均幀數會降到很低。為了避免這種情況,可以嘗試開啟 CALayer.shouldRasterize 屬性,但這會把原本離屏渲染的操作轉嫁到 CPU 上去。
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的如何做一个流畅的UI 组内分享记录的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手把手教你webpack3(3)入口(多
- 下一篇: SQL优化常用方法9