新聞中心
Flutter ScrollView(滾動(dòng)視圖)
ScrollView 是一個(gè)帶有滾動(dòng)的視圖組件。
目前創(chuàng)新互聯(lián)公司已為成百上千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)頁(yè)空間、網(wǎng)站運(yùn)營(yíng)、企業(yè)網(wǎng)站設(shè)計(jì)、開(kāi)平網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
ScrollView 由三部分組成:
ScrollView 有以下常用屬性:
注:ScrollView 是一個(gè)抽象類,通常使用 CustomScrollView。
SliverAppBar 可以實(shí)現(xiàn)背景,標(biāo)題,頂部導(dǎo)航欄聯(lián)動(dòng),漸隱漸出動(dòng)畫。
Flutter動(dòng)態(tài)化方案調(diào)研
騰訊課堂14M
今日頭條3M
閑魚22M
百度貼吧13M
螞蟻財(cái)富56.8M
百度網(wǎng)盤14M
手機(jī)淘寶15M
貝殼找房8M
由粗粒度小組件動(dòng)態(tài)拼裝出頁(yè)面,Native端已經(jīng)有很多成熟的框架,如天貓的Tangram。
開(kāi)發(fā)語(yǔ)言:iOS、Android
適用場(chǎng)景:快速迭代的活動(dòng)營(yíng)銷頁(yè)面
優(yōu)點(diǎn):無(wú)侵入,更新簡(jiǎn)單
缺點(diǎn):提前預(yù)埋,擴(kuò)展性差,靈活性差
以webview作為容器的app,歷史悠久,最早到2011年。
開(kāi)發(fā)語(yǔ)言:HTML
適用場(chǎng)景:雙端嚴(yán)格一致的銀行類app,容器類的支付寶小程序等
優(yōu)點(diǎn):動(dòng)態(tài)更新,跨平臺(tái)
缺點(diǎn):性能,加載速度
UI用Xml+JS表達(dá),用Native View渲染。
開(kāi)發(fā)語(yǔ)言:Xml+JS
適用場(chǎng)景:雙端嚴(yán)格一致的銀行類app,容器類的支付寶小程序等
優(yōu)點(diǎn):native組件,生態(tài)成熟
缺點(diǎn):三方庫(kù)crash,性能缺陷
UI用Dart表達(dá),用Dart engine渲染。
Flutter官方不支持動(dòng)態(tài)化。原因是Flutter在 Release 模式下構(gòu)建的是 AOT 編譯產(chǎn)物,在 Debug 模式下構(gòu)建的是 JIT ,AOT 依賴的 Dart VM 和 JIT 并不一樣, JIT Release 并不支持 iOS 設(shè)備??尚械姆桨甘牵篈OT 需要一個(gè)編譯后的 “Dart VM”。抽離一份 DartVM 獨(dú)立編譯,再以動(dòng)態(tài)庫(kù)的形式引入項(xiàng)目。
開(kāi)發(fā)語(yǔ)言:Dart
適用場(chǎng)景:iOS、Android、Web、Desktop、Embed
優(yōu)點(diǎn):性能最佳
缺點(diǎn):增大包體積 20MB+
大廠的主流方案。UI用JS表達(dá),用Dart engine渲染。
開(kāi)發(fā)語(yǔ)言:JS、類JS
適用場(chǎng)景:iOS、Android
優(yōu)點(diǎn):性能最佳
缺點(diǎn):需要掌握J(rèn)S、Dart兩個(gè)語(yǔ)言和框架
大廠的主流方案。UI用Dart表達(dá),用Dart engineX渲染。
開(kāi)發(fā)語(yǔ)言:Dart
適用場(chǎng)景:iOS、Android
優(yōu)點(diǎn):性能最佳
缺點(diǎn):需要改造Dart engine
1、 美團(tuán)外賣Flutter動(dòng)態(tài)化實(shí)踐
2、 攜程App 首頁(yè)動(dòng)態(tài)化探索
3、 Flutter 動(dòng)態(tài)化在最右 App 中的實(shí)踐
4、 Flutter 動(dòng)態(tài)化熱更新的思考與實(shí)踐
5、 NOW直播Flutter動(dòng)態(tài)搜索列表頁(yè)實(shí)現(xiàn)
6、 Flutter動(dòng)態(tài)化的方案對(duì)比及最佳實(shí)現(xiàn)-閑魚
7、 基于JavaScript 的MXFlutter
Flutter組件(Widget)的局部刷新方式
Flutter中有兩個(gè)常用的狀態(tài)Widget分為StatefulWidget和StatelessWidget,分別為動(dòng)態(tài)視圖和靜態(tài)視圖,視圖的更新需要調(diào)用StatefulWidget的setState方法,這會(huì)遍歷調(diào)用子Widget的build方法。如果一個(gè)頁(yè)面內(nèi)容比較復(fù)雜時(shí),會(huì)包含多個(gè)widget,如果直接調(diào)用setState,會(huì)遍歷所有子Widget的build,這樣會(huì)造成很多不必要的開(kāi)銷,所以非常有必要了解Flutter中局部刷新的方式:
globalkey唯一定義了某個(gè)element,它使你能夠訪問(wèn)與element相關(guān)聯(lián)的其他對(duì)象,例如buildContext、state等。應(yīng)用場(chǎng)景:跨widget訪問(wèn)狀態(tài)。
例如:可以通過(guò)key.currentState拿到它的狀態(tài)對(duì)象,然后就可以調(diào)用其中的onPressed方法。
Flutter框架內(nèi)部提供了一個(gè)非常小巧精致的組件,專門用于局部組件的刷新。適用于值改動(dòng)的刷新。
實(shí)現(xiàn)原理:在 initState 中對(duì)傳入的可監(jiān)聽(tīng)對(duì)象進(jìn)行監(jiān)聽(tīng),執(zhí)行 _valueChanged 方法,_valueChanged 中進(jìn)行了 setState 來(lái)觸發(fā)當(dāng)前狀態(tài)的刷新。觸發(fā) build 方法,從而觸發(fā) widget.builder 回調(diào),這樣就實(shí)現(xiàn)了局部刷新??梢钥吹竭@里回調(diào)的 child 是組件傳入的 child,所以直接使用,這就是對(duì) child 的優(yōu)化的根源。
可以看到 ValueListenableBuilder 實(shí)現(xiàn)局部刷新的本質(zhì),也是進(jìn)行組件的抽離,讓組件狀態(tài)的改變框定在狀態(tài)內(nèi)部,并通過(guò) builder 回調(diào)控制局部刷新,暴露給用戶使用。
通過(guò)這個(gè)可以創(chuàng)建一個(gè)支持局部刷新的widget樹,比如你可以在StatelessWidget里面刷新某個(gè)布局,但是不需要改變成StatefulWidget;也可以在StatefulWidget中使用做部分刷新而不需要刷新整個(gè)頁(yè)面,這個(gè)刷新是不會(huì)調(diào)用Widget build(BuildContext context)刷新整個(gè)布局樹的。
異步UI更新:
很多時(shí)候我們會(huì)依賴一些異步數(shù)據(jù)來(lái)動(dòng)態(tài)更新UI,比如在打開(kāi)一個(gè)頁(yè)面時(shí)我們需要先從互聯(lián)網(wǎng)上獲取數(shù)據(jù),在獲取數(shù)據(jù)的過(guò)程中顯示一個(gè)加載框,等獲取到數(shù)據(jù)時(shí)我們?cè)黉秩卷?yè)面;又比如我們想展示Stream(比如文件流、互聯(lián)網(wǎng)數(shù)據(jù)接收流)的進(jìn)度。當(dāng)然StatefulWidget我們完全可以實(shí)現(xiàn)以上功能。但由于在實(shí)際開(kāi)發(fā)中依賴異步數(shù)據(jù)更新UI的這種場(chǎng)景非常常見(jiàn),并且當(dāng)StatefulWidget中控件樹較大時(shí),更新一個(gè)屬性導(dǎo)致整個(gè)樹重建,消耗性能,因此Flutter專門提供了FutureBuilder和SteamBuilder兩個(gè)組件來(lái)快速實(shí)現(xiàn)這種功能。
通常情況下,子Widget無(wú)法單獨(dú)感知父Widget的變化,當(dāng)父state變化時(shí),通過(guò)其build重建所有子widget;
InheriteddWidget可以避免這種全局創(chuàng)建,實(shí)現(xiàn)局部子Widget更新。InheritedWidget提供了一種在Widget樹中從上到下傳遞、共享數(shù)據(jù)的方式。Flutter SDK正是通過(guò)InheritedWidget來(lái)共享應(yīng)用主題和Locale等信息。
InheritedWidgetData
TestData
InheritedTest1Page
provider是Google I/O 2019大會(huì)上宣布的現(xiàn)在官方推薦的管理方式,而ChangeNotifierProvider可以說(shuō)是Provider的一種:
yaml文件需要引入provider: ^3.1.0
頂層嵌套ChangeNotifierProvider
創(chuàng)建共享數(shù)據(jù)類DataInfo:
數(shù)據(jù)類需要with ChangeNotifier 以使用 notifyListeners()函數(shù)通知監(jiān)聽(tīng)者更新界面。
使用Provider.of(context)獲取DataInfo
nextPage:
使用Consumer包住需要使用共享數(shù)據(jù)的Widget
RepaintBoundary就是重繪邊界,用于重繪時(shí)獨(dú)立于父視圖。頁(yè)面需要更新的頁(yè)面結(jié)構(gòu)可以用 RepaintBoundary組件嵌套,flutter 會(huì)將包含的組件獨(dú)立出一層"畫布",去繪制。官方很多組件 外層也包了層 RepaintBoundary 標(biāo)簽。如果你的自定義view比較復(fù)雜,應(yīng)該盡可能的避免重繪。
以上總結(jié)了幾種Flutter的局部刷新的方式,可根據(jù)實(shí)際需要使用不同的方式,最適合的才是最好的。
Flutter局部刷新方法
Flutter中Widget分為StatefulWidget和StatelessWidget,分別為動(dòng)態(tài)視圖和靜態(tài)視圖,視圖的更新需要調(diào)用StatefulWidget的setState方法,這會(huì)遍歷調(diào)用子Widget的build方法。當(dāng)一個(gè)主頁(yè)面比較復(fù)雜時(shí),會(huì)包含多個(gè)widget,如果直接調(diào)用setState,會(huì)遍歷所有子Widget的build,這是非常不必要的性能開(kāi)銷,有沒(méi)有單獨(dú)刷新指定Widget的方式呢?這個(gè)時(shí)候就要用到GlobalKey了。
一個(gè)StatefulWidget包含一個(gè)Button,一個(gè)Text,通過(guò)點(diǎn)擊Button調(diào)用主Widget的setState方法,刷新Text,示例如下:
同樣一個(gè)StatefulWidget包含一個(gè)多個(gè)Text和Button,點(diǎn)擊Button我們只需要刷新指定的Text,通過(guò)GlobalKey的方式,實(shí)現(xiàn)如下:
主Widget,包含一個(gè)需要更新的TextWidget和一個(gè)不需要更新的Text
需要單獨(dú)更新的Widget
傳遞事件的Button
這樣點(diǎn)擊Button就只會(huì)更新指定的TextWidget了,效果如下:
這只是一個(gè)簡(jiǎn)單的例子,在實(shí)際開(kāi)發(fā)中為了頁(yè)面刷新的高效率,模塊化封裝非常重要。很多情況下都只需要局部刷新,而不是重構(gòu)整個(gè)視圖。所以Globalkey的運(yùn)用在項(xiàng)目中需要熟練掌握
網(wǎng)站題目:flutter動(dòng)態(tài)視圖的簡(jiǎn)單介紹
文章鏈接:http://www.dlmjj.cn/article/dsgcode.html