Stateful(有狀態(tài)) 和 stateless(無狀態(tài)) widgets
站在用戶的角度思考問題,與客戶深入溝通,找到開平網(wǎng)站設(shè)計與開平網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都網(wǎng)站建設(shè)、做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、域名注冊、網(wǎng)絡(luò)空間、企業(yè)郵箱。業(yè)務(wù)覆蓋開平地區(qū)。
stateless widget 沒有內(nèi)部狀態(tài). Icon、 IconButton, 和Text 都是無狀態(tài)widget, 他們都是 StatelessWidget的子類。
stateful widget 是動態(tài)的. 用戶可以和其交互 (例如輸入一個表單、 或者移動一個slider滑塊),或者可以隨時間改變 (也許是數(shù)據(jù)改變導(dǎo)致的UI更新). Checkbox, Radio, Slider, InkWell, Form, and TextField 都是 stateful widgets, 他們都是 StatefulWidget的子類。
StatefulWidget類
具有可變狀態(tài)的小部件。
狀態(tài)是(1)在構(gòu)建窗口小部件時可以同步讀取的信息,以及(2)在窗口小部件的生命周期內(nèi)可能會更改的信息。這是小工具實施者的責任,以確保國家的及時通知當這種狀態(tài)的改變,使用State.setState。
有狀態(tài)窗口小部件是一個窗口小部件,它通過構(gòu)建一個更具體地描述用戶界面的其他窗口小部件來描述用戶界面的一部分。構(gòu)建過程以遞歸方式繼續(xù),直到用戶界面的描述完全具體(例如,完全由RenderObjectWidget組成,其描述具體的RenderObject)。
當您描述的用戶界面部分可以動態(tài)更改時(例如由于具有內(nèi)部時鐘驅(qū)動狀態(tài)或依賴于某些系統(tǒng)狀態(tài)),狀態(tài)窗口小部件非常有用。對于僅依賴于對象本身中的配置信息以及窗口小部件膨脹的 BuildContext的組合,請考慮使用 StatelessWidget。
StatefulWidget實例本身是不可變的,并且將它們的可變狀態(tài)存儲在由createState方法創(chuàng)建的單獨State對象中 ,或者存儲在State訂閱的對象中,例如Stream或ChangeNotifier對象,其引用存儲在StatefulWidget的最終字段中本身。
框架在膨脹StatefulWidget時 調(diào)用createState,這意味著如果該窗口小部件已插入到多個位置的樹中,則多個State對象可能與同一StatefulWidget關(guān)聯(lián)。同樣,如果StatefulWidget從樹中移除,后來在樹再次插入時,框架將調(diào)用createState再創(chuàng)建一個新的國家目標,簡化的生命周期狀態(tài)的對象。
如果StatefulWidget的創(chuàng)建者使用GlobalKey作為其 鍵,則StatefulWidget在從樹中的一個位置移動到另一個位置時保持相同的State對象。由于具有GlobalKey的窗口小部件可以在樹中的至多一個位置使用,因此使用GlobalKey的窗口小部件最多只有一個關(guān)聯(lián)元素。當通過將與該窗口小部件關(guān)聯(lián)的(唯一)子樹從舊位置移植到新位置(而不是在該位置重新創(chuàng)建子樹)時,框架利用此屬性將全局鍵從樹中的一個位置移動到另一個位置時利用此屬性。新的位置)。與StatefulWidget關(guān)聯(lián)的State對象與子樹的其余部分一起被移植,這意味著State對象在新位置被重用(而不是被重新創(chuàng)建)。但是,為了有資格進行嫁接,必須將窗口小部件插入到從舊位置移除它的同一動畫幀中的新位置。
StatefulWidget有兩個主要類別。
首先是其中一個分配資源State.initState并在他們的處置State.dispose,但不依賴于InheritedWidget S或致電State.setState。這些小部件通常在應(yīng)用程序或頁面的根目錄中使用,并通過ChangeNotifier, Stream或其他此類對象與子小部件進行通信。遵循這種模式的有狀態(tài)小部件相對便宜(就CPU和GPU周期而言),因為它們構(gòu)建一次然后永不更新。因此,它們可能有一些復(fù)雜和深刻的構(gòu)建方法。
第二類是使用State.setState或依賴于 InheritedWidget的小部件。這些通常會在應(yīng)用程序的生命周期內(nèi)重建多次,因此最小化重建此類窗口小部件的影響非常重要。(他們也可以使用State.initState或 State.didChangeDependencies并分配資源,但重要的是他們重建。)
可以使用幾種技術(shù)來最小化重建有狀態(tài)窗口小部件的影響:
StatelessWidget類
一個不需要可變狀態(tài)的小部件。
無狀態(tài)窗口小部件是一個窗口小部件,它通過構(gòu)建一個更具體地描述用戶界面的其他窗口小部件來描述用戶界面的一部分。構(gòu)建過程以遞歸方式繼續(xù),直到用戶界面的描述完全具體(例如,完全由RenderObjectWidget組成,其描述具體的RenderObject)。
當您描述的用戶界面部分不依賴于對象本身的配置信息以及窗口小部件膨脹的BuildContext時,無狀態(tài)窗口小部件非常有用。對于可以動態(tài)更改的組合,例如由于具有內(nèi)部時鐘驅(qū)動狀態(tài)或依賴于某些系統(tǒng)狀態(tài),請考慮使用StatefulWidget。
無狀態(tài)窗口小部件的構(gòu)建方法通常僅在以下三種情況下調(diào)用:第一次將窗口小部件插入樹中,窗口小部件的父窗口更改其配置時,以及何時依賴于更改的InheritedWidget。
如果窗口小部件的父級將定期更改窗口小部件的配置,或者它依賴于經(jīng)常更改的繼承窗口小部件,則優(yōu)化構(gòu)建方法的性能以保持流暢的呈現(xiàn)性能非常重要。
可以使用幾種技術(shù)來最小化重建無狀態(tài)窗口小部件的影響:
在Tree中從上往下高效傳遞數(shù)據(jù)的基類widget , 定義為:abstract class InheritedWidget extends ProxyWidget
Flutter的響應(yīng)式開發(fā)與React類似,數(shù)據(jù)都是自頂向下的。
假設(shè)有祖先組點A,中間經(jīng)過結(jié)點B, C,然后到結(jié)點D,D需要從A中獲取數(shù)據(jù)f,那按照自頂向下數(shù)據(jù)流轉(zhuǎn),f需要依次傳遞給B及C,最后才到C。這樣開發(fā)極為不靈活,成本也比較高。所有Flutter需要有跨結(jié)點(只能是祖先后代節(jié)點,不能跨兄弟節(jié)點)高效傳遞數(shù)據(jù)的方案。
大體意思如下:
InheritedWidget 是在樹中高效向下傳遞信息的基類部件;
調(diào)用[BuildContext.inheritFromWidgetOfExactType]方法可以從 BuildContext 中獲取到最近的 InheritedWidget 類型的實例;
在 InheritedWidget 類型的控件被引用,也就是調(diào)用過 inheritFromWidgetOfExactType 方法后,當 InheritedWidget 自身狀態(tài)改變時,會導(dǎo)致引用了 InheritedWidget 類型的子控件重構(gòu)(rebuild)。
這里隨便定義一個人 Person 類。
創(chuàng)建一個類繼承 InheritedWidget,并實現(xiàn) updateShouldNotify 方法。
之前說到調(diào)用[BuildContext.inheritFromWidgetOfExactType]方法可以從 BuildContext 中獲取到最近的 InheritedWidget 類型的實例,所以此處定義一個靜態(tài)的 of 方法,通過傳入的 context 獲取到最近的 InheriedDataWidget 實例。
1.定義數(shù)據(jù)模型
這里隨便定義一個 Person 類。
2.自定義 InheritedWidget 控件類
創(chuàng)建一個類繼承 InheritedWidget,并實現(xiàn) updateShouldNotify 方法。
之前說到調(diào)用[BuildContext.inheritFromWidgetOfExactType]方法可以從 BuildContext 中獲取到最近的 InheritedWidget 類型的實例,所以此處定義一個靜態(tài)的 of 方法,通過傳入的 context 獲取到最近的 InheriedDataWidget 實例。
3.InheriedDataWidget 的使用
InheriedDataWidget 使用起來也很簡單,它本身也是一個控件,只要在任意一個頁面的子控件調(diào)用其構(gòu)造方法就行,這里我們定義一個形如的 Widget 樹。
WidgetA 是一個 StatefulWidget 類型的控件,可以調(diào)用 setState 刷新,如果是繼承人 Stateless 類型的控件,那我們也可以通過 Stream 或者其他方式刷新數(shù)據(jù),感興趣的請看[什么是 Stream? Dart
WidgetA1_1 類
WidgetA1_2 類
WidgetA1_3 類
當我們點擊 floatingActionButton 的時候,WidgetA1, WidgetA1_1, WidgetA1_2 的控件都會更新 Person 的信息,而且每點 floatingActionButton 一次, 當我們點擊 floatingActionButton 的時候,WidgetA1, WidgetA1_1, WidgetA1_2 的控件都會更新 Person 的信息,而且每點 floatingActionButton 一次,都會輸出:
如果我們試圖在和 WidgetA 的同一層級的兄弟節(jié)點去訪問 InheriedDataWidget 的 Person 數(shù)據(jù),是不行的,因為父節(jié)點中并沒有插入 InheriedDataWidget。
把 WidgetB 和 WidgetA 保持同一節(jié)點
這也體現(xiàn)了 Inheried(遺傳) 這一單詞的特性,遺傳只存在于父子。兄弟不存在遺傳的關(guān)系。
這種數(shù)據(jù)共享的方式在某些場景還是很有用的,就比如說全局主題,字體大小,字體顏色的變更,只要在 App 根層級共享出這些配置數(shù)據(jù),然后在觸發(fā)數(shù)據(jù)改變之后,所有引用到這些共享數(shù)據(jù)的地方都會刷新,這換主題,字體是不是就很輕松,事實上 Theme.of(context).primaryColor 之流就是這么干的。
以上就是有關(guān)InheritedWidget的使用。
自己也是從事Android開發(fā)5年有余了;整理了一些Android開發(fā)技術(shù)核心筆記和面經(jīng)題綱,有關(guān)更多Android開發(fā)進階技術(shù)資料、面經(jīng)題綱、核心技術(shù)筆記; 想要進階自己、拿高薪的同學(xué)請私信我回復(fù)“核心筆記”或“面試”領(lǐng)??!
row : 在水平方向上排列子widget的列表.
Row 是繼承 Flex = MultiChildRenderObjectWidget = RenderObjectWidget = Widget .
所以 Row 具有動態(tài)布局的特點,可以讓子控件展開以填充可水平的可用空間,用一個 Expanded 的控件包裹子控件。
Row 不支持滾動(通常認為一行的子控件超過可以容納空間是錯誤的)。如果有一行控件控件比較多,希望可以滑動的時候,可以采用 ListView 。
同樣,如果是垂直方向方面和 Row 對應(yīng)的是 Column 。
小demo
這里需要注意的地方:
因為在 Row 里面有text,但是因為text的長度過長,一行肯定是放不下的,所以這里考慮用Expanded包裹一個Text,這樣文字會自動換行,填充剩余部分。
效果圖如下
修改下Row的 內(nèi)容:
效果如下:可見多個Expanded 具有平分剩余空間的功能。和android 的weight 屬性很相像。
Dart中的繼承:
1.子類使用extends關(guān)鍵詞來繼承父類
2.子類會繼承父類里面可見的屬性和方法,但是不會繼承構(gòu)造函數(shù)
3.子類能復(fù)寫父類的方法 getter和setter
子類使用extends關(guān)鍵詞來繼承父類
子類里面可以擴展自己屬性和方法
ClipRect控件默認是通過限制子widget的繪制區(qū)域來達到裁剪的效果的,通過custom clipper,可以自定義裁剪的大小跟坐標
ClipRect的定義如下
ClipRect class默認是沒有任何裁剪效果的,需要通過clipper參數(shù)告訴ClipRect如何去裁剪,clipper是個CustomClipper類型,CustomClipper是個抽象接口類,我們通過繼承CustomClipper,重寫 getClip 方法可以定義一個裁剪區(qū)域,通過重寫 shouldReclip 方法來告訴ClipRect當一個新的clipper被設(shè)置了是否需要更新裁剪區(qū)域,譬如開始設(shè)置的clipper裁剪坐標是從(10,10)開始的,新設(shè)置的clipper裁剪坐標是(20,20),那么shouldReclip需要返回true來通知ClipRect更新裁剪區(qū)域。
下面這個例子從網(wǎng)絡(luò)上加載一張圖片,并且進行裁剪,裁剪坐標是(10,10) 裁剪的寬高是圖片的寬高減去10
效果如下
Flutter是一個移動應(yīng)用程序的軟件開發(fā)工具包(SDK),具有以下特征:
跨平臺應(yīng)用的框架,沒有使用WebView或者系統(tǒng)平臺自帶的控件,使用自身的高性能渲染引擎自繪
簡化版的瀏覽器,最大限度在android和ios上統(tǒng)一UI,包括業(yè)務(wù)邏輯和用戶體驗
開發(fā)語言使用dart,結(jié)合C, C++, 和Skia(2D渲染引擎)構(gòu)建
支持hot reload,包含著完整的控件和工具鏈
一切皆控件,控件是每個Flutter應(yīng)用程序的基本構(gòu)建塊,與分離視圖、控制器、布局和其他屬性的框架不同,F(xiàn)lutter具有一致的統(tǒng)一對象模型:控件。一個控件可以定義:結(jié)構(gòu)元素(比如按鈕或菜單)、風格元素(比如字體或顏色方案)、布局的方面(比如填充)、一些業(yè)務(wù)邏輯等
組合大于繼承,控件本身通常由許多小型、單用途的控件組成,結(jié)合起來產(chǎn)生強大的效果,類的層次結(jié)構(gòu)是扁平的,以最大化可能的組合數(shù)量
強化版的WebView,框架僅提供一個View層,大部分功能要依賴原生
目前只能夠運行大部分Dart代碼(不能引入dart:mirrors或dart:html庫)