Flutter中Widget分為StatefulWidget和StatelessWidget,分別為動(dòng)態(tài)視圖和靜態(tài)視圖,視圖的更新需要調(diào)用StatefulWidget的setState方法,這會(huì)遍歷調(diào)用子Widget的build方法。當(dāng)一個(gè)主頁面比較復(fù)雜時(shí),會(huì)包含多個(gè)widget,如果直接調(diào)用setState,會(huì)遍歷所有子Widget的build,這是非常不必要的性能開銷,有沒有單獨(dú)刷新指定Widget的方式呢?這個(gè)時(shí)候就要用到GlobalKey了。
創(chuàng)新互聯(lián)于2013年成立,先為阿瓦提等服務(wù)建站,阿瓦提等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為阿瓦提企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。
一個(gè)StatefulWidget包含一個(gè)Button,一個(gè)Text,通過點(diǎn)擊Button調(diào)用主Widget的setState方法,刷新Text,示例如下:
同樣一個(gè)StatefulWidget包含一個(gè)多個(gè)Text和Button,點(diǎn)擊Button我們只需要刷新指定的Text,通過GlobalKey的方式,實(shí)現(xiàn)如下:
主Widget,包含一個(gè)需要更新的TextWidget和一個(gè)不需要更新的Text
需要單獨(dú)更新的Widget
傳遞事件的Button
這樣點(diǎn)擊Button就只會(huì)更新指定的TextWidget了,效果如下:
這只是一個(gè)簡單的例子,在實(shí)際開發(fā)中為了頁面刷新的高效率,模塊化封裝非常重要。很多情況下都只需要局部刷新,而不是重構(gòu)整個(gè)視圖。所以Globalkey的運(yùn)用在項(xiàng)目中需要熟練掌握
描述了屏幕上指針(觸摸、鼠標(biāo)、觸控筆)的位置和移動(dòng)。
Flutter中可以使用Listener(功能性組件)來監(jiān)聽原始觸摸事件
例1
例2
例3
忽略PointerEvent
手勢: 描述由一個(gè)或多個(gè)指針移動(dòng)組成的語義動(dòng)作,如拖動(dòng)、縮放、雙擊等。
Material大多數(shù)widget已經(jīng)對tap或手勢做出了響應(yīng)。 例如 IconButton和 FlatButton 響應(yīng)單擊,ListView響應(yīng)滑動(dòng)事件觸發(fā)滾動(dòng)。
用于手勢識(shí)別的功能性組件,通過它可以來識(shí)別各種手勢。
例(單擊)
例(添加Material觸摸水波效果 InkWell組件)
例(滑動(dòng)關(guān)閉 Dismissable組件)
例(單擊、雙擊、長按)
例(滑動(dòng))
例(掃動(dòng)---單一方向)
例(縮放)
GestureRecognizer是一個(gè)抽象類。
一種手勢的識(shí)別器對應(yīng)一個(gè)GestureRecognizer的子類。
例
由于手勢競爭最終只有一個(gè)勝出者,所以,當(dāng)有多個(gè)手勢識(shí)別器時(shí),可能會(huì)產(chǎn)生沖突。
例
例
在APP中經(jīng)常會(huì)需要一個(gè)廣播機(jī)制,用以跨頁面通知。比如一個(gè)需要登錄的APP中,頁面會(huì)關(guān)注用戶登錄或注銷事件,來進(jìn)行一些狀態(tài)更新。
這時(shí)候,一個(gè)事件總線便會(huì)非常有用,事件總線通常實(shí)現(xiàn)了訂閱者模式,訂閱者模式包含發(fā)布者和訂閱者兩種角色,可以通過事件總線來觸發(fā)事件和監(jiān)聽事件。
對于一些簡單的應(yīng)用,事件總線是足以滿足業(yè)務(wù)需求的,如果決定使用狀態(tài)管理包的話,一定要想清楚APP是否真的有必要使用它,防止“化簡為繁”、過度設(shè)計(jì)。
例
在widget樹中,每一個(gè)節(jié)點(diǎn)都可以分發(fā)通知,通知會(huì)沿著當(dāng)前節(jié)點(diǎn)向上傳遞,所有父節(jié)點(diǎn)都可以通過NotificationListener來監(jiān)聽通知。
Flutter中將這種由子向父的傳遞通知的機(jī)制稱為通知冒泡(Notification Bubbling)。
通知冒泡和用戶觸摸事件冒泡是相似的,但有一點(diǎn)不同:通知冒泡可以中止,但用戶觸摸事件不行。
通知冒泡和Web開發(fā)中瀏覽器事件冒泡原理是相似的,都是事件從出發(fā)源逐層向上傳遞,可以在上層節(jié)點(diǎn)任意位置來監(jiān)聽通知/事件,也可以終止冒泡過程,終止冒泡后,通知將不會(huì)再向上傳遞。
Flutter的UI框架實(shí)現(xiàn)中,除了在可滾動(dòng)組件在滾動(dòng)過程中會(huì)發(fā)出ScrollNotification之外,還有一些其它的通知,如SizeChangedLayoutNotification、KeepAliveNotification 、LayoutChangedNotification等,F(xiàn)lutter正是通過這種通知機(jī)制來使父元素可以在一些特定時(shí)機(jī)來做一些事情。
例
例
例
阻止冒泡
通知冒泡原理
Flutter (二)布局
Flutter (三) 狀態(tài)管理
Flutter (四) Map轉(zhuǎn)模型
Flutter (五) 網(wǎng)絡(luò)請求
Flutter (六) 保留界面狀態(tài)
Flutter (七) 混合開發(fā) [配置]
Flutter (八) 混合開發(fā) [Flutter完整項(xiàng)目嵌入到原生]
狀態(tài)可變的 widget 。
通過其類的定義能夠看到 StatefulWidget 配置 StatefulElement 。
State 是 StatefulWidget 的內(nèi)部邏輯與狀態(tài),由 StatefulWidget 的 createState 創(chuàng)建。
StatefulWidget 實(shí)例本身是不可變的, 但是 StatefulWidget 將其可變的狀態(tài),存儲(chǔ)在與之關(guān)聯(lián)的 State 對象中。
不管什么時(shí)候,只要在樹中 mount 一個(gè)新的 StatefulElement ,必然需要注入一個(gè) StatefulWidget ,注入一個(gè) StatefulWidget 時(shí), framework 都會(huì)調(diào)用一次 createState 方法。
其實(shí),在 StatefulElement 構(gòu)造的時(shí)候,就會(huì)調(diào)用 createState ,創(chuàng)建 _state 對象,( _state 是 StatefulElement 的變量)并且在 StatefulElement 的初始化方法中為 _state 關(guān)聯(lián)當(dāng)前的 StatefulElement 和用以配置 StatefulElement 的 StatefulWidget 。
StatefulElement 初始化方法如下:
這意味著如果 StatefulWidget 被插入到樹中的多個(gè)位置,則會(huì)有多個(gè) State 對象分別與它們關(guān)聯(lián)。
關(guān)于此類的定義如下:
描述: 重寫此方法以執(zhí)行初始化。
場景: 如果 State 的 build 方法依賴于本身可以改變狀態(tài)的對象時(shí)。(例如 ChangeNotifier 或 Stream ,或者可以訂閱并接收通知的其他對象)正確的方式是:
注意點(diǎn): 此方法中不能使用 BuildContext.dependOnInheritedWidgetOfExactType 。但是此方法被調(diào)用后會(huì)立即調(diào)用 didChangeDependencies ,在 didChangeDependencies 可以使用 BuildContext.dependOnInheritedWidgetOfExactType 。
調(diào)用時(shí)機(jī): StatefulElement ,首次插入樹中時(shí)會(huì)調(diào)用此方法,在 build 方法調(diào)用之前調(diào)用。
描述: StatefulElement 通過此方法返回的 widget 并通過調(diào)用 updateChild 來更新自己。
調(diào)用時(shí)機(jī): framework 調(diào)用此方法的幾個(gè)不同的場景如下:
描述: StatefulElement 存在,并且符合 Widget.canUpdate 的情況下對 StatefulWidget 進(jìn)行更新。
調(diào)用時(shí)機(jī): 不論何時(shí)只要 StatefulElement 的配置 widget 改變的時(shí)候就會(huì)調(diào)用。
注意: didUpdateWidget 方法最終會(huì)調(diào)用 build 方法,因此在此方法中調(diào)用 setState 是多余的。如果重寫此方法,請確保調(diào)用 super.didUpdateWidget(oldWidget) 。
調(diào)用時(shí)機(jī): 當(dāng)此 State 對象的依賴項(xiàng)( InheritedWidget )更改時(shí)調(diào)用。
描述: 用于開發(fā)階段 hot reload 。
調(diào)用時(shí)機(jī): hot reload 時(shí)調(diào)用,調(diào)用后 build 方法也將被調(diào)用。無需在此方法中做任何操作。
調(diào)用時(shí)機(jī): 當(dāng) StatefulElement 從樹中移除的時(shí)候會(huì)調(diào)用。
調(diào)用時(shí)機(jī): 當(dāng) StatefulElement 從樹中 unmount 的時(shí)候會(huì)調(diào)用。
StatefulWidget 用以配置 StatefulElement ,但在這兩者之間的 State 承接了 StatefulElement 的生命周期,而 StatefulWidget 僅僅只是連接了 State 與 StatefulElement 的不可變的實(shí)例,因此 StatefulWidget 的生命周期,依賴于 StatefulElement ,而 State 卻是其最簡單直接的體現(xiàn)形式。
為了能更好的理解 StatefulWidget 的生命周期,我畫了一張關(guān)于 State 、 StatefulElement 、 Component 、 Element 的關(guān)系圖。
在此之前先推薦看大佬的: 填坑指導(dǎo)
iOS需要注意:
1、flutter2.0要求cocoapods 升級(jí)到1.9.0
詳情看這篇博客
2、原來flutter項(xiàng)目中的podfile文件是舊版本的ccocoapods了,刪除podfile和對應(yīng)的.lock,然后flutter項(xiàng)目重新運(yùn)行使用它自動(dòng)生成的podfile文件
3、安裝CocoaPods
卸載cocoapods:sudo gem uninstall cocoapods
查看cocoapods版本:pod --version
指定版本安裝:
sudo gem install -n /usr/local/bin cocoapods -v 1.9.3(新MacOS系統(tǒng)升級(jí))
不指定版本安裝
sudo gem install -n /usr/local/bin cocoapods
說明 :老項(xiàng)目sdk1.17.0===升級(jí)到2.0.1,當(dāng)前所有操作基于win平臺(tái)
到此為止環(huán)境已經(jīng)準(zhǔn)備妥當(dāng),正式進(jìn)入項(xiàng)目修改。
所有的插件都要適配到空安全,插件是否支持均會(huì)有對應(yīng)說明Null safety,適配過程不確定版本的話,可以使用dio: any,適配完事后再在pubspec.lock文件中查看具體的版本修改過來,實(shí)在有部分插件沒有支持的,參考下面
部分插件在適配空安全的版本放棄維護(hù)了,得自行更新或?qū)ふ姨娲纾?flutter_swiper 變?yōu)?flutter_swiper_null_safety ,插件更新后要注意項(xiàng)目中的用法是否需要更新
2.1.1: 以前采用的是 provide 插件共享全局?jǐn)?shù)據(jù),現(xiàn)在變化為 provider ,用法改變, 點(diǎn)擊參考 ,以防文章丟失,我重復(fù)一遍:
比如:
2.1.2: dio版本升級(jí)到4.0.0最新版后,部分用法改變
2.2.1
2.2.2
解決方案:
2.2.3
解決方案:
2.2.4
解決方案:
2.2.5
解決方案:
2.2.6
解決方案:
2.2.7
解決方案:
2.2.8
解決方案: child 換為sliver
2.2.8.1
解決方案: 項(xiàng)目目錄下: android--app-build.gradle --minSdkVersion改為:18 或者19
2.2.8.2
解決方案: 在pubspec.yarm管理里面添加:publish_to
2.2.8.3
解決方案: video_player升級(jí)后字段發(fā)生了變化,initialized字段更換為:isInitialized(_controller.value.isInitialized)
2.2.8.4
解決方案:
2.2.8.5
解決方案:
2.2.8.6
解決方案: 方案一:刪除ios目錄下的Podfile.lock 文件然后重新運(yùn)行 pod install命令
方案二:刪除ios目錄下的Podfile.lock與Podfile文件 重新運(yùn)行flutter run或flutter build ios
方案三:刪除ios目錄,重新運(yùn)行 flutter create . 命令,注意有"."這個(gè)符號(hào)不要忘記
2.2.8.7
這個(gè)報(bào)錯(cuò)一般對應(yīng)的就是下面的報(bào)錯(cuò),注意看后面的報(bào)錯(cuò)信息,看是哪個(gè)插件報(bào)錯(cuò)。
解決方案: 把Podfile的版本注釋打開,改為platform :ios, '9.0' 或者是更高的版本
全局替換
1.將new List() 替換為[];
2.TextField的inputFormatters:[WhitelistingTextInputFormatter.digitsOnly] 替換為[FilteringTextInputFormatter.digitsOnly]
3.TextField的inputFormatters:[WhitelistingTextInputFormatter(RegExp("[a-z|A-Z|0-9]"))]替換為FilteringTextInputFormatter.allow(RegExp("[a-z|A-Z|0-9]"))
4.Stack組件中overflow: Overflow.visible改為 clipBehavior: Clip.none;overflow: Overflow.clip改為clipBehavior:Clip.hardEdge
5.ListWheelScrollView組件中clipToSize = false改為clipBehavior: Clip.none,clipToSize = true改為 Clip.hardEdge
6.TextField中maxLengthEnforced: true改為maxLengthEnforcement:MaxLengthEnforcement.enforced
7.FlatButton、RaisedButton、OutlineButton的變化: 官方參考
顏色的屬性發(fā)生了變化,由原來的Color 變?yōu)榱薓aterialStatePropertyColor, 這是未了解決不同狀態(tài)(pressed、hovered、focused、disabled)下按鈕顏色的變化
例如
8.出現(xiàn)如下警告
9.showSnackBar報(bào)錯(cuò)誤
解決方案: Scaffold換為ScaffoldMessenger
10.textSelectionColor棄用
解決方案:
11.charts_flutter升級(jí)后屬性報(bào)錯(cuò)
解決方案:
12.flutter 真機(jī)調(diào)試無法訪問網(wǎng)絡(luò),dio報(bào)錯(cuò)
解決方案:
android:
ios:
問題12完整參考
針對日常不同的需求,我們時(shí)常需要自定義 Dialog ,而小菜在嘗試過程中遇到一些小問題,簡單記錄總結(jié)一下;
小菜在自定義含有文本框的 Dialog 時(shí),文本框獲取焦點(diǎn)時(shí),軟鍵盤會(huì)部分遮擋對話框,但當(dāng)小菜替換為 AlertDialog 時(shí),文本框獲取焦點(diǎn)時(shí),對話框會(huì)向上浮動(dòng),避免軟鍵盤遮擋;
對于含有文本框的自定義 Dialog ,小菜在最外層使用的是 Material 嵌套,小菜通過采用 Scaffold 來嵌套處理,默認(rèn) Scaffold 中 resizeToAvoidBottomPadding / resizeToAvoidBottomInset 為 true ,當(dāng)設(shè)置為 false 時(shí),文本框獲取焦點(diǎn)時(shí),依舊會(huì)被軟鍵盤遮擋;因?yàn)樵诠潭ㄇ榫翱梢耘浜? resizeToAvoidBottomPadding 實(shí)現(xiàn)是否被軟鍵盤遮擋效果;
resizeToAvoidBottomPadding 主要用于自身 Widget 是否避免被其他窗口遮擋;其中小菜查資料介紹在 Flutter 1.1.9 之后更推薦使用 resizeToAvoidBottomInset ;
小菜自定義一個(gè)可以多選 item 的 Dialog ,但 Dialog 中并沒有狀態(tài)更新的 State ,如何進(jìn)行 Dialog 中狀態(tài)更新呢?
小菜之前在 showDialog 時(shí)直接創(chuàng)建了 TypeListDialog ,此時(shí)是無狀態(tài)的,當(dāng) WidgetBuilder 創(chuàng)建一個(gè) StatefulBuilder 有狀態(tài)的構(gòu)造器即可,可以將 state 傳遞到 Dialog 中;
小菜在自定義 Dialog 時(shí)如何在一個(gè)回調(diào)方法中傳遞多個(gè)參數(shù)?
小菜在 Dialog 的回調(diào)方法中傳遞兩個(gè) List ,而在接收回調(diào)方法中匹配兩個(gè)參數(shù)即可;小菜簡單看作是一個(gè)函數(shù)方法;
小菜在重寫 AppBar 時(shí),如何取消默認(rèn)的返回按鈕?
取消 AppBar 前面的返回圖標(biāo)有多種方式;
自定義 Dialog 案例源碼
小菜對于 Flutter 的應(yīng)用還不夠熟悉,很多常用的場景會(huì)處理的很不到位,小菜會(huì)對日常的小問題進(jìn)行簡單記錄,逐步學(xué)習(xí);如有錯(cuò)誤,請多多指導(dǎo)!
文章標(biāo)題:Flutter狀態(tài)更新,flutter 自動(dòng)更新
本文鏈接:http://vcdvsql.cn/article38/dsdeisp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站維護(hù)、品牌網(wǎng)站制作、小程序開發(fā)、響應(yīng)式網(wǎng)站、品牌網(wǎng)站設(shè)計(jì)、靜態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(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)