真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網站制作重慶分公司

flutter重繪邊界的簡單介紹

Flutter -Listview 4個優(yōu)化能讓你的列表絲般順滑

優(yōu)化點1:使用 builder構建列表

成都創(chuàng)新互聯(lián)是一家集網站建設,欒城企業(yè)網站建設,欒城品牌網站建設,網站定制,欒城網站建設報價,網絡營銷,網絡優(yōu)化,欒城網站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學習、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網站。

當你的列表元素是動態(tài)增長的時候(比如上拉加載更多),請不要直接用children 的方式,一直往children 的數(shù)組增加組件,那樣會很糟糕。對于 ListView.builder 是按需構建列表元素,也就是只有那些可見得元素才會調用itemBuilder 構建元素,這樣對于大列表而言性能開銷自然會小很多。

優(yōu)化點2:禁用 addAutomaticKeepAlives 和 addRepaintBoundaries 特性

這兩個屬性都是為了優(yōu)化滾動過程中的用戶體驗的。

addAutomaticKeepAlives 特性默認是 true,意思是在列表元素不可見后可以保持元素的狀態(tài),從而在再次出現(xiàn)在屏幕的時候能夠快速構建。這其實是一個拿空間換時間的方法,會造成一定程度得內存開銷??梢栽O置為 false 關閉這一特性。缺點是滑動過快的時候可能會出現(xiàn)短暫的白屏(實際會很少發(fā)生)。

addRepaintBoundaries 是將列表元素使用一個重繪邊界(Repaint Boundary)包裹,從而使得滾動的時候可以避免重繪。而如果列表很容易繪制(列表元素布局比較簡單的情況下)的時候,可以關閉這個特性來提高滾動的流暢度。

優(yōu)化點3:盡可能將列表元素中不變的組件使用 const 修飾

使用 const 相當于將元素緩存起來實現(xiàn)共用,若列表元素某些部分一直保持不變,那么可以使用 const 修飾。

優(yōu)化點4:使用 itemExtent 確定列表元素滾動方向的尺寸

對于很多列表,我們在滾動方向上的尺寸是提前可以根據 UI設計稿知道的,如果能夠知道的話,那么使用 itemExtent 屬性制定列表元素在滾動方向的尺寸,可以提升性能。這是因為,如果不指定的話,在滾動過程中,會需要推算每個元素在滾動方向的尺寸從而消耗計算資源。

Flutter ListView 的4個優(yōu)化要點,非常實用哦!實際上,這些要點都可以從官網的文檔里找出對應得說明。因此,如果遇到了性能問題,除了搜索引擎外,也建議多看看官方的文檔。

回到前臺黑屏引發(fā)對Flutter項目生命周期與安卓原生生命周期的思考

目前我們是flutter項目,有個需求是需要在app內引導用戶去appStore或是安卓的應用商店去評價,該需求我選用了兩個插件 in_app_review 和 launch_review , 然而仔做的過程中發(fā)現(xiàn)一個問題,當彈出系統(tǒng)的跳轉應用商店的彈框時,iOS是單一彈框,Android是彈出一個選擇打開商店的彈窗,可選擇打開一次或是始終選擇某一個商店打開,此時鎖屏,然后再解鎖,發(fā)現(xiàn)iOS沒啥問題,安卓系統(tǒng)彈框后的flutter頁面黑屏了

看到這個現(xiàn)象,目測是由于安卓的生命周期和flutter的生命周期沒有同步,以下是驗證過程

安卓的MainActivity添加生命周期方法

flutter 添加生命周期方法

還是剛才的場景 鎖屏 安卓和flutter的后臺方法都調用,解鎖回到前臺 只有安卓的前臺方法走 MainActivity會restart,flutter的resume方法,沒有調用,驗證了開始的猜想,是由于flutter沒有檢測到前臺操作或是這種情況flutter不認為自己在前臺,導致flutter沒有執(zhí)行頁面的重新繪制導致黑屏

關于flutter的生命周期,查閱資料發(fā)現(xiàn) 我們可以手動刷新flutter頁面的狀態(tài),即使用

我們只需要在MainActivity restart的時候調用上述 方法 告知flutter重繪,該問題就解決了

關于原生加載flutter頁面 生命周期相關 看這里 能有一些啟發(fā)

Flutter性能優(yōu)化

1.圓角對性能的影響

盡量避免用Clipxxx組件,建議用BoxDecoration的image屬性實現(xiàn),如果用Clipxxx組件,圓角取整后性能會提升。

2.減少重繪

根據場景合理使用RePaintBoundary,使繪制獨立于父布局,避免重繪,提升性能,但過度使用增加的圖層會帶來Raster合成的耗時。例如scrollview是滑動過程會導致所有的節(jié)點都重繪,可以在scrollview下一層使用RePaintBoundary。

3.滾動步長插值器優(yōu)化(了解)

官方的滾動差值器在出現(xiàn)小卡頓時,滾動步長會出現(xiàn)大的跳躍,導致體感上出現(xiàn)很明顯的抖動,優(yōu)化步長偏移量算法與原生效果對齊。

4.開啟SurfaceView

官方推薦Flutter用SurfaceView ,因為SurfaceView與應用窗口內容分隔開,在專有硬件中合成,產生的中間副本少于TextureView,所以性能高,占用內存少,但是在混合棧遇到的問題需要突破

5.使用RepaintBoundary 提升頻繁重繪控件的性能。使用RelayoutBoundary提升頻繁修改大小,增刪的布局中也可以提升性能。

6.build中不要去寫大量的耗時邏輯,因為數(shù)據更新會觸發(fā)build的多次調用,在里面做耗時邏輯會降低性能。

7.盡量使用statelessWidget代替statefulWidget,因為statefulWidget的銷毀重建會引起子widget的銷毀與重建。

8.解析json可以放到子線程線程中,開Isolate去解析,這樣,當返回數(shù)據特別大的時候也不會阻塞界面。

9.使用不變的組件的時候可以添加const,const組件不會進行build更新

10.由于flutter通過widget.runtimeType和key來判斷是否需要跟新組建,所以我們寫組件的時候盡量保持key不變,或者不寫key。對于一些需要頻繁改變,例如新增、刪除、排序的最好加上key。如果type一直,如果不寫key容易導致,element無法區(qū)分新舊widget,導致無法更新。

Flutter組件(Widget)的局部刷新方式

Flutter中有兩個常用的狀態(tài)Widget分為StatefulWidget和StatelessWidget,分別為動態(tài)視圖和靜態(tài)視圖,視圖的更新需要調用StatefulWidget的setState方法,這會遍歷調用子Widget的build方法。如果一個頁面內容比較復雜時,會包含多個widget,如果直接調用setState,會遍歷所有子Widget的build,這樣會造成很多不必要的開銷,所以非常有必要了解Flutter中局部刷新的方式:

globalkey唯一定義了某個element,它使你能夠訪問與element相關聯(lián)的其他對象,例如buildContext、state等。應用場景:跨widget訪問狀態(tài)。

例如:可以通過key.currentState拿到它的狀態(tài)對象,然后就可以調用其中的onPressed方法。

Flutter框架內部提供了一個非常小巧精致的組件,專門用于局部組件的刷新。適用于值改動的刷新。

實現(xiàn)原理:在 initState 中對傳入的可監(jiān)聽對象進行監(jiān)聽,執(zhí)行 _valueChanged 方法,_valueChanged 中進行了 setState 來觸發(fā)當前狀態(tài)的刷新。觸發(fā) build 方法,從而觸發(fā) widget.builder 回調,這樣就實現(xiàn)了局部刷新。可以看到這里回調的 child 是組件傳入的 child,所以直接使用,這就是對 child 的優(yōu)化的根源。

可以看到 ValueListenableBuilder 實現(xiàn)局部刷新的本質,也是進行組件的抽離,讓組件狀態(tài)的改變框定在狀態(tài)內部,并通過 builder 回調控制局部刷新,暴露給用戶使用。

通過這個可以創(chuàng)建一個支持局部刷新的widget樹,比如你可以在StatelessWidget里面刷新某個布局,但是不需要改變成StatefulWidget;也可以在StatefulWidget中使用做部分刷新而不需要刷新整個頁面,這個刷新是不會調用Widget build(BuildContext context)刷新整個布局樹的。

異步UI更新:

很多時候我們會依賴一些異步數(shù)據來動態(tài)更新UI,比如在打開一個頁面時我們需要先從互聯(lián)網上獲取數(shù)據,在獲取數(shù)據的過程中顯示一個加載框,等獲取到數(shù)據時我們再渲染頁面;又比如我們想展示Stream(比如文件流、互聯(lián)網數(shù)據接收流)的進度。當然StatefulWidget我們完全可以實現(xiàn)以上功能。但由于在實際開發(fā)中依賴異步數(shù)據更新UI的這種場景非常常見,并且當StatefulWidget中控件樹較大時,更新一個屬性導致整個樹重建,消耗性能,因此Flutter專門提供了FutureBuilder和SteamBuilder兩個組件來快速實現(xiàn)這種功能。

通常情況下,子Widget無法單獨感知父Widget的變化,當父state變化時,通過其build重建所有子widget;

InheriteddWidget可以避免這種全局創(chuàng)建,實現(xiàn)局部子Widget更新。InheritedWidget提供了一種在Widget樹中從上到下傳遞、共享數(shù)據的方式。Flutter SDK正是通過InheritedWidget來共享應用主題和Locale等信息。

InheritedWidgetData

TestData

InheritedTest1Page

provider是Google I/O 2019大會上宣布的現(xiàn)在官方推薦的管理方式,而ChangeNotifierProvider可以說是Provider的一種:

yaml文件需要引入provider: ^3.1.0

頂層嵌套ChangeNotifierProvider

創(chuàng)建共享數(shù)據類DataInfo:

數(shù)據類需要with ChangeNotifier 以使用 notifyListeners()函數(shù)通知監(jiān)聽者更新界面。

使用Provider.of(context)獲取DataInfo

nextPage:

使用Consumer包住需要使用共享數(shù)據的Widget

RepaintBoundary就是重繪邊界,用于重繪時獨立于父視圖。頁面需要更新的頁面結構可以用 RepaintBoundary組件嵌套,flutter 會將包含的組件獨立出一層"畫布",去繪制。官方很多組件 外層也包了層 RepaintBoundary 標簽。如果你的自定義view比較復雜,應該盡可能的避免重繪。

以上總結了幾種Flutter的局部刷新的方式,可根據實際需要使用不同的方式,最適合的才是最好的。

Flutter解決界面超出bug

如上圖,最右邊有黃色斑馬線類似的線。

在這里查找源碼

可以看到,F(xiàn)lutter在這里做的處理

_calculateOverflowRegions這個方法,計算界面是否超出邊界,如果超出了

就添加一個斑馬線的布局,可以通過修改源碼的方式,暫時讓他隱藏

直接return就可以了。

當然,F(xiàn)lutter這樣是為了更好的提示開發(fā)者,方便開發(fā)的。平時調試的時候還是要打開的。除非上線,如果不放心的話,可以這么寫。

Flutter面試:渲染原理

頁面中的各界面元素(Widget)以樹的形式組織,即控件樹。Flutter通過控件樹中的每個控件創(chuàng)建不同類型的渲染對象,組成渲染對象樹。而渲染對象樹在Flutter的展示過程分為三個階段:布局、繪制、合成和渲染。

(一)布局

Flutter采用深度優(yōu)先機制遍歷渲染對象樹,決定渲染對象樹中各渲染對象在屏幕上的位置和尺寸。在布局過程中,渲染對象樹中的每個渲染對象都會接收父對象的布局約束參數(shù),決定自己的大小,然后父對象按照控件邏輯決定各個子對象的位置,完成布局過程。

為了防止因子節(jié)點發(fā)生變化而導致整個控件樹重新布局,F(xiàn)lutter加入了一個機制——布局邊界(Relayout Boundary),可以在某些節(jié)點自動或手動地設置布局邊界,當邊界內的任何對象發(fā)生重新布局時,不會影響邊界外的對象,反之亦然。

二)繪制

布局完成后,渲染對象樹中的每個節(jié)點都有了明確的尺寸和位置。Flutter會把所有的渲染對象繪制到不同的圖層上。與布局過程一樣,繪制過程也是深度優(yōu)先遍歷,而且總是先繪制自身,再繪制子節(jié)點。

以下圖為例:節(jié)點1在繪制完自身后,會再繪制節(jié)點2,然后繪制它的子節(jié)點3、4和5,最后繪制節(jié)點6。

可以看到,由于一些其他原因(比如,視圖手動合并)導致2的子節(jié)點5與它的兄弟節(jié)點6處于了同一層,這樣會導致當節(jié)點2需要重繪的時候,與其無關的節(jié)點6也會被重繪,帶來性能損耗。

為了解決這一問題,F(xiàn)lutter提出了與布局邊界對應的機制——重繪邊界(Repaint Boundary)。在重繪邊界內,F(xiàn)lutter會強制切換新的圖層,這樣就可以避免邊界內外的互相影響,避免無關內容置于同一圖層引起不必要的重繪。

重繪邊界的一個典型場景是Scrollview。ScrollView滾動的時候需要刷新視圖內容,從而觸發(fā)內容重繪。而當滾動內容重繪時,一般情況下其他內容是不需要重繪的,這時候重繪邊界就派上用場了。

(三)合成和渲染

終端設備的頁面越來越復雜,因此Flutter的渲染樹層級通常很多,直接交付給渲染引擎進行多圖層渲染,可能會出現(xiàn)大量渲染內容的重復繪制,所以還需要先進行一次圖層合成,即將所有的圖層根據大小、層級、透明度等規(guī)則計算出最終的顯示效果,將相同的圖層歸類合并,簡化渲染樹,提高渲染效率。

合并完成后,F(xiàn)lutter會將幾何圖層數(shù)據交由Skia引擎加工成二維圖像數(shù)據,最終交由GPU進行渲染,完成界面的展示。

四、總結

咱們從各種業(yè)界主流跨端方案與Flutter的對比開始,到Flutter的簡要介紹以及Flutter的運行機制,并以界面渲染過程為例,從布局、繪制、合成和渲染三個階段講述了Flutter的實現(xiàn)原理。相信大家對Flutter已經有一個整體認知,趕快一起上手操作起來吧!


本文標題:flutter重繪邊界的簡單介紹
URL鏈接:http://weahome.cn/article/pheiod.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部