頁面中的各界面元素(Widget)以樹的形式組織,即控件樹。Flutter通過控件樹中的每個(gè)控件創(chuàng)建不同類型的渲染對象,組成渲染對象樹。而渲染對象樹在Flutter的展示過程分為三個(gè)階段:布局、繪制、合成和渲染。
站在用戶的角度思考問題,與客戶深入溝通,找到廣豐網(wǎng)站設(shè)計(jì)與廣豐網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊、虛擬空間、企業(yè)郵箱。業(yè)務(wù)覆蓋廣豐地區(qū)。
(一)布局
Flutter采用深度優(yōu)先機(jī)制遍歷渲染對象樹,決定渲染對象樹中各渲染對象在屏幕上的位置和尺寸。在布局過程中,渲染對象樹中的每個(gè)渲染對象都會接收父對象的布局約束參數(shù),決定自己的大小,然后父對象按照控件邏輯決定各個(gè)子對象的位置,完成布局過程。
為了防止因子節(jié)點(diǎn)發(fā)生變化而導(dǎo)致整個(gè)控件樹重新布局,F(xiàn)lutter加入了一個(gè)機(jī)制——布局邊界(Relayout Boundary),可以在某些節(jié)點(diǎn)自動(dòng)或手動(dòng)地設(shè)置布局邊界,當(dāng)邊界內(nèi)的任何對象發(fā)生重新布局時(shí),不會影響邊界外的對象,反之亦然。
二)繪制
布局完成后,渲染對象樹中的每個(gè)節(jié)點(diǎn)都有了明確的尺寸和位置。Flutter會把所有的渲染對象繪制到不同的圖層上。與布局過程一樣,繪制過程也是深度優(yōu)先遍歷,而且總是先繪制自身,再繪制子節(jié)點(diǎn)。
以下圖為例:節(jié)點(diǎn)1在繪制完自身后,會再繪制節(jié)點(diǎn)2,然后繪制它的子節(jié)點(diǎn)3、4和5,最后繪制節(jié)點(diǎn)6。
可以看到,由于一些其他原因(比如,視圖手動(dòng)合并)導(dǎo)致2的子節(jié)點(diǎn)5與它的兄弟節(jié)點(diǎn)6處于了同一層,這樣會導(dǎo)致當(dāng)節(jié)點(diǎn)2需要重繪的時(shí)候,與其無關(guān)的節(jié)點(diǎn)6也會被重繪,帶來性能損耗。
為了解決這一問題,F(xiàn)lutter提出了與布局邊界對應(yīng)的機(jī)制——重繪邊界(Repaint Boundary)。在重繪邊界內(nèi),F(xiàn)lutter會強(qiáng)制切換新的圖層,這樣就可以避免邊界內(nèi)外的互相影響,避免無關(guān)內(nèi)容置于同一圖層引起不必要的重繪。
重繪邊界的一個(gè)典型場景是Scrollview。ScrollView滾動(dòng)的時(shí)候需要刷新視圖內(nèi)容,從而觸發(fā)內(nèi)容重繪。而當(dāng)滾動(dòng)內(nèi)容重繪時(shí),一般情況下其他內(nèi)容是不需要重繪的,這時(shí)候重繪邊界就派上用場了。
(三)合成和渲染
終端設(shè)備的頁面越來越復(fù)雜,因此Flutter的渲染樹層級通常很多,直接交付給渲染引擎進(jìn)行多圖層渲染,可能會出現(xiàn)大量渲染內(nèi)容的重復(fù)繪制,所以還需要先進(jìn)行一次圖層合成,即將所有的圖層根據(jù)大小、層級、透明度等規(guī)則計(jì)算出最終的顯示效果,將相同的圖層歸類合并,簡化渲染樹,提高渲染效率。
合并完成后,F(xiàn)lutter會將幾何圖層數(shù)據(jù)交由Skia引擎加工成二維圖像數(shù)據(jù),最終交由GPU進(jìn)行渲染,完成界面的展示。
四、總結(jié)
咱們從各種業(yè)界主流跨端方案與Flutter的對比開始,到Flutter的簡要介紹以及Flutter的運(yùn)行機(jī)制,并以界面渲染過程為例,從布局、繪制、合成和渲染三個(gè)階段講述了Flutter的實(shí)現(xiàn)原理。相信大家對Flutter已經(jīng)有一個(gè)整體認(rèn)知,趕快一起上手操作起來吧!
1.圓角對性能的影響
盡量避免用Clipxxx組件,建議用BoxDecoration的image屬性實(shí)現(xiàn),如果用Clipxxx組件,圓角取整后性能會提升。
2.減少重繪
根據(jù)場景合理使用RePaintBoundary,使繪制獨(dú)立于父布局,避免重繪,提升性能,但過度使用增加的圖層會帶來Raster合成的耗時(shí)。例如scrollview是滑動(dòng)過程會導(dǎo)致所有的節(jié)點(diǎn)都重繪,可以在scrollview下一層使用RePaintBoundary。
3.滾動(dòng)步長插值器優(yōu)化(了解)
官方的滾動(dòng)差值器在出現(xiàn)小卡頓時(shí),滾動(dòng)步長會出現(xiàn)大的跳躍,導(dǎo)致體感上出現(xiàn)很明顯的抖動(dòng),優(yōu)化步長偏移量算法與原生效果對齊。
4.開啟SurfaceView
官方推薦Flutter用SurfaceView ,因?yàn)镾urfaceView與應(yīng)用窗口內(nèi)容分隔開,在專有硬件中合成,產(chǎn)生的中間副本少于TextureView,所以性能高,占用內(nèi)存少,但是在混合棧遇到的問題需要突破
5.使用RepaintBoundary 提升頻繁重繪控件的性能。使用RelayoutBoundary提升頻繁修改大小,增刪的布局中也可以提升性能。
6.build中不要去寫大量的耗時(shí)邏輯,因?yàn)閿?shù)據(jù)更新會觸發(fā)build的多次調(diào)用,在里面做耗時(shí)邏輯會降低性能。
7.盡量使用statelessWidget代替statefulWidget,因?yàn)閟tatefulWidget的銷毀重建會引起子widget的銷毀與重建。
8.解析json可以放到子線程線程中,開Isolate去解析,這樣,當(dāng)返回?cái)?shù)據(jù)特別大的時(shí)候也不會阻塞界面。
9.使用不變的組件的時(shí)候可以添加const,const組件不會進(jìn)行build更新
10.由于flutter通過widget.runtimeType和key來判斷是否需要跟新組建,所以我們寫組件的時(shí)候盡量保持key不變,或者不寫key。對于一些需要頻繁改變,例如新增、刪除、排序的最好加上key。如果type一直,如果不寫key容易導(dǎo)致,element無法區(qū)分新舊widget,導(dǎo)致無法更新。
本文將從三個(gè)方面介紹Android 圖形系統(tǒng)。
圖形系統(tǒng)提供繪圖和圖形處理支持。
Android 框架提供了各種用于 2D 和 3D 圖形渲染的 API、圖片解碼庫,以及各種Driver支持。
? 繪圖API:2D引擎 Skia,3D引擎 OpenGL ES,RenderScript,OpenCV和Vulkan。
? 圖片解碼庫:jpg,png,gif等。
應(yīng)用開發(fā)者可通過三種方式將圖像繪制到屏幕:
? Canvas : 2D圖形API,Android View樹實(shí)際的繪制者。
? OpenGL ES : 嵌入式設(shè)備的OpenGL 三維圖形API子集。
? Vulkan :跨平臺的2D和3D繪圖引擎,Android 7.0后支持,NDK。
整個(gè)圖形系統(tǒng)架構(gòu)是一個(gè)生產(chǎn)者和消費(fèi)者模式,五層依次介紹:
2D繪制:Canvas api / view 的子類 (button ,list)/自定義view
3D繪制:應(yīng)用直接使用OpenGL 接口繪制圖形(PixelFlinger對應(yīng)的是openGl 1.0 ,GUP driver 對應(yīng)的是2.0和3.0)
所有情況下的繪圖都渲染到一個(gè)包含 GraphicBuffer的Surface上,當(dāng)一塊 Surface 顯示在屏幕上時(shí),就是用戶所看到的窗口。
? Canvas:畫布,2D圖形API,Android View樹實(shí)際的渲染者。
? Skia繪制:Android4.0之前默認(rèn)使用,主線程通過CPU完成繪圖指令操作,在復(fù)雜場景下單幀容易超過16ms導(dǎo)致卡頓。
WindowManagerService(WMS)窗口管理服務(wù),管理系統(tǒng)中所有的窗口。
? 管理window (view的容器)
? Window與surface對應(yīng),一塊顯示區(qū)域。添加一個(gè)window,就是 WMS 為其分配一塊 Surface 的過程。
Google 在Android source官網(wǎng)提示:
這里就對這些控件進(jìn)行簡單介紹:
Surface : Handle onto a raw buffer that is being managed by the screen compositor.
Surface 對應(yīng)一塊屏幕緩沖區(qū)。生產(chǎn)者是: SurfaceTexture、MediaRecorder 等,消費(fèi)者是: OpenGL、MediaPlayer 或 CameraDevice等。每個(gè)window對應(yīng)一個(gè)Surface。Canvas或OpenGL ES等最終都渲染到Surface上。
? Flutter在Android平臺上也是直接渲染到Surface。例如:一個(gè)Activity/Dialog都是一個(gè)Surface,它承載了上層的圖形數(shù)據(jù),與SurfaceFlinger側(cè)的Layer相對應(yīng)。
Canvas(畫布)實(shí)現(xiàn)由 Skia 圖形庫提供。為了確保兩個(gè)客戶端不會同時(shí)更新某個(gè)緩沖區(qū),使用以下命令處理畫布鎖:
使用雙緩沖機(jī)制,有自己的 surface,View只是一個(gè)透明的占位符,Surface可以在后臺線程中繪制。雙緩沖機(jī)制提高渲染效率,獨(dú)立線程
繪制,提升流暢性。適合一些場景:需要界面迅速更新、UI繪制時(shí)間長、對幀率要求較高的情況。
提供訪問和控制Surface 相關(guān)的方法 。通過SurfaceView的getHolder()函數(shù)可以獲取SurfaceHolder對象,Surface 就在SurfaceHolder對象內(nèi)。
addCallback(SurfaceHolder.Callbackcallback) /Canvas lockCanvas() /unlockCanvasAndPost(Canvascanvas)
SurfaceTexture: Surface 和 OpenGL ES (GLES) 紋理(Texture)的組合。將圖像流轉(zhuǎn)為 OpenGL 外部紋理。
TextureView:持有 SurfaceTexture,將圖像處理為 OpenGL 紋理更新到 HardwareLayer。
GLSurfaceView:加入 EGL 管理,自帶 GL 上下文和 GL 渲染線程
這些View通常涉及到Android音視頻相關(guān),需要高效的渲染能力。如下面的SurfaceTexture在camera中的應(yīng)用。
簡稱Buffer, 一個(gè)Buffer包含一幀圖像,Buffer由gralloc分配和回收。Buffer 屬性包含:width, height, format, usage等
BufferQueue 的引入是為了解決顯示和性能問題。
? Surface屬于APP進(jìn)程,Layer屬于系統(tǒng)進(jìn)程,如果它們之間只用一個(gè)Buffer,會存在顯示和性能問題。
? 一些Buffer用于繪制,一些Buffer用于顯示,雙方處理完之后,交換一下Buffer,提高效率。
? BufferQueue中包含多個(gè)Buffer對象。
Android圖形系統(tǒng)包含了兩對生產(chǎn)者和消費(fèi)者模型,它們都通過BufferQueue進(jìn)行連接:
1.Canvas和OpenGL ES生產(chǎn)圖形數(shù)據(jù),SurfaceFlinger消費(fèi)圖形數(shù)據(jù)。
2.SurfaceFlinger合成所有圖層的圖形數(shù)據(jù),Display顯示合成結(jié)果。
code:frameworks/native/services/surfaceflinger
? Surface表示APP進(jìn)程的一個(gè)窗口,承載了窗口的圖形數(shù)據(jù)。
? SurfaceFlinger是系統(tǒng)進(jìn)程合成所有窗口的系統(tǒng)服務(wù),負(fù)責(zé)合成所有Surface提供的圖形數(shù)據(jù),然后送顯到屏幕。
? SurfaceFlinger既是上層應(yīng)用的消費(fèi)者,又是Display的生產(chǎn)者,起到了承上啟下的作用。
數(shù)據(jù)流:
合成示意圖:
在介紹Vsync機(jī)制之前先介紹兩個(gè)重要概念:
屏幕刷新率:屏幕每秒鐘可以刷新多少次。60HZ刷新率,16.7ms刷新一次。(120HZ/8.3ms),硬件指標(biāo)。
GPU 繪制幀率:GPU 每秒能夠合成繪制多少幀。
軟件層觸發(fā) View 繪制的時(shí)機(jī)是隨機(jī)的,當(dāng)下一次屏幕刷新時(shí),屏幕從 Frame Buffer 中拿到的數(shù)據(jù)還是“幀1”的數(shù)據(jù),導(dǎo)致“丟幀”。
每隔 16ms 硬件層發(fā)出 vsync 信號,應(yīng)用層接收到此信號后會觸發(fā)UI 的渲染流程,同時(shí) vsync 信號也會觸發(fā) SurfaceFlinger 讀取Buffer 中的數(shù)據(jù),進(jìn)行合成顯示到屏幕上。
總結(jié):Vsync機(jī)制將 CPU 和 GPU 的開始時(shí)間與屏幕刷新強(qiáng)行拖拽到同一起跑線
Android提供的Graphics流程相對比較復(fù)雜對其進(jìn)行具象后的流程如下兩張圖所示:
網(wǎng)站名稱:flutter圖層,flutter 圖片列表
標(biāo)題鏈接:http://m.rwnh.cn/article22/dscodcc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營銷推廣、虛擬主機(jī)、定制網(wǎng)站、微信小程序、網(wǎng)站維護(hù)、外貿(mào)網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)