最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Flutter快學(xué)快用24講--06 生命周期:掌握 Flutter 生命周期以及應(yīng)用場景

2023-03-16 22:30 作者:gzqhero  | 我要投稿

本課時將介紹 Flutter 的組件,以及組件的生命周期,其次結(jié)合上課時的例子實現(xiàn)一個自動更新展示最新時間的 Flutter 應(yīng)用。

組件 Widget

Flutter 中的組件與前端組件的理解和作用基本一致,但是沒有一個明確的概念解釋 Flutter 組件,這里我借用前端的組件定義來解釋 Flutter 組件的概念。

一個 Flutter 組件,包含了組件的模板、樣式和交互等內(nèi)容,外部只要按照組件設(shè)定的屬性、函數(shù)及事件處理等進(jìn)行調(diào)用即可,完全不用考慮組件的內(nèi)部實現(xiàn)邏輯。其中組件又包括無狀態(tài)組件和有狀態(tài)組件。

  • 無狀態(tài)組件

無狀態(tài)組件,可以理解為將外部傳入的數(shù)據(jù)轉(zhuǎn)化為界面展示的內(nèi)容,只會渲染一次。

  • 有狀態(tài)組件

有狀態(tài)組件,是定義交互邏輯和業(yè)務(wù)數(shù)據(jù),可以理解為具有動態(tài)可交互的內(nèi)容界面,會根據(jù)數(shù)據(jù)的變化進(jìn)行多次渲染。

生命周期

在原生 Android 、原生 iOS 、前端 React 或者 Vue 都存在生命周期的概念,在 Flutter 中一樣存在生命周期的概念,其基本概念和作用相似。 Flutter 中說的生命周期,也是指有狀態(tài)組件,對于無狀態(tài)組件生命周期只有 build 這個過程,也只會渲染一次,而有狀態(tài)組件則比較復(fù)雜,下面我們就來看看有狀態(tài)組件的生命周期過程。

生命周期的流轉(zhuǎn)

Flutter 中的生命周期,包含以下幾個階段:

  • createState ,該函數(shù)為 StatefulWidget 中創(chuàng)建 State 的方法,當(dāng) StatefulWidget 被調(diào)用時會立即執(zhí)行 createState 。

  • initState ,該函數(shù)為 State 初始化調(diào)用,因此可以在此期間執(zhí)行 State 各變量的初始賦值,同時也可以在此期間與服務(wù)端交互,獲取服務(wù)端數(shù)據(jù)后調(diào)用 setState 來設(shè)置 State。

  • didChangeDependencies ,該函數(shù)是在該組件依賴的 State 發(fā)生變化時,這里說的 State 為全局 State ,例如語言或者主題等,類似于前端 Redux 存儲的 State 。

  • build ,主要是返回需要渲染的 Widget ,由于 build 會被調(diào)用多次,因此在該函數(shù)中只能做返回 Widget 相關(guān)邏輯,避免因為執(zhí)行多次導(dǎo)致狀態(tài)異常。

  • reassemble ,主要是提供開發(fā)階段使用,在 debug 模式下,每次熱重載都會調(diào)用該函數(shù),因此在 debug 階段可以在此期間增加一些 debug 代碼,來檢查代碼問題。

  • didUpdateWidget ,該函數(shù)主要是在組件重新構(gòu)建,比如說熱重載,父組件發(fā)生 build 的情況下,子組件該方法才會被調(diào)用,其次該方法調(diào)用之后一定會再調(diào)用本組件中的 build 方法。

  • deactivate ,在組件被移除節(jié)點(diǎn)后會被調(diào)用,如果該組件被移除節(jié)點(diǎn),然后未被插入到其他節(jié)點(diǎn)時,則會繼續(xù)調(diào)用 dispose 永久移除。

  • dispose ,永久移除組件,并釋放組件資源。


image (7).png

圖 1 生命周期流程圖

整個過程分為四個階段:

  1. 初始化階段,包括兩個生命周期函數(shù) createState 和 initState;

  2. 組件創(chuàng)建階段,也可以稱組件出生階段,包括 didChangeDependencies 和 build;

  3. 觸發(fā)組件多次 build ,這個階段有可能是因為 didChangeDependencies、setState 或者 didUpdateWidget 而引發(fā)的組件重新 build ,在組件運(yùn)行過程中會多次被觸發(fā),這也是優(yōu)化過程中需要著重需要注意的點(diǎn);

  4. 最后是組件銷毀階段,deactivate 和 dispose。

組件首次加載執(zhí)行過程

我們先實現(xiàn)一段代碼,來看下組件在首次創(chuàng)建的執(zhí)行過程是否是按照圖 1 的流程。

1、 在 lib 中 pages 下創(chuàng)建 test_stateful_widget.dart ;

2、 在 test_stateful_widget.dart 添加如下代碼:

上述代碼把有狀態(tài)組件的一些生命周期函數(shù)都進(jìn)行了重寫,并且在執(zhí)行中都打印了一些字符串標(biāo)識,目的是可以看到該函數(shù)被執(zhí)行。

3、 然后在 main.dart 中加載該組件,代碼如下:

代碼修改后,我們打開手機(jī)模擬器,然后運(yùn)行該 App ,在輸出控制臺可以看到下面的運(yùn)行打印日志信息。

運(yùn)行結(jié)果中,打印過程可以看到是按照我們上面圖 1 的執(zhí)行流程在運(yùn)行的, 但其中最值得關(guān)注的是 build 運(yùn)行了兩次。這是在開發(fā)模式下才會執(zhí)行的過程,在正式環(huán)境是不會出現(xiàn)的,因為重新渲染成本非常大,這個問題可以使用打印 build 的調(diào)用堆棧即可發(fā)現(xiàn)。如果你要關(guān)閉兩次 build 也可以實現(xiàn),在 Flutter 框架中搜索 constants.dart 文件,并找到下面這行代碼,將 defaultValue 從 false 修改為 true。

其實這里會 觸發(fā) didUpdateWidget 函數(shù),是因為 TestStatefulWidget 組件是 MyApp 組件中的子組件,從而導(dǎo)致 MyApp 函數(shù)中的 build 觸發(fā)子組件 didUpdateWidget 函數(shù)的執(zhí)行,具體會在下面觸發(fā)組件再次 build 中詳細(xì)說明。

觸發(fā)組件再次 build

觸發(fā)組件再次 build 有三種方式,一個是 setState ,另一個是 didChangeDependencies ,再一個是 didUpdateWidget 。

setState 比較容易理解,在數(shù)據(jù)狀態(tài)進(jìn)行變化時,觸發(fā)組件 build ,在上面的代碼運(yùn)行后的界面中,點(diǎn)擊中間的頁面提示如圖 2 位置,就可以看到在調(diào)用 setState 后,會調(diào)用 build 一個方法。


image (8).png

圖 2 測試組件運(yùn)行界面

didChangeDependencies ,你可以理解為本組件依賴的全局 state 的值發(fā)生了變化,例如前端的 redux 中的數(shù)據(jù)發(fā)生了變化,也會進(jìn)行 build 操作。一般情況下我們會將一些比較基礎(chǔ)的數(shù)據(jù)放到全局變量中,例如主題顏色、地區(qū)語言或者其他通用變量等。如果這些全局 state 發(fā)生狀態(tài)變化則會觸發(fā)該函數(shù),而該函數(shù)之后就會觸發(fā) build 操作。

didUpdateWidget 觸發(fā) build 我們需要從代碼層面來講解下,現(xiàn)在我們需要設(shè)計兩個組件,一個是我們剛實現(xiàn)的 TestStatefulWidget ,另外一個則是該組件的子組件,我們命名為SubStatefulWidget 。接下來我們在 TestStatefulWidget 加載該組件,在頭部 import 該組件,然后將 build 中的代碼修改為下面:

接下來我們實現(xiàn) SubStatefulWidget 子組件的代碼,和父組件基本相似,只是在打印處都加了 sub ,其次 build 實現(xiàn)邏輯也修改了,具體代碼如下:

代碼實現(xiàn)完成后,我們再重新加載 App ,可以看到如下運(yùn)行日志信息。

  • 加載 TestStatefulWidget 組件,四個狀態(tài)函數(shù) createState、initState、didChangeDependencies 和 build;

  • 加載 SubStatefulWidget 組件,四個狀態(tài)函數(shù) createState、initState、didChangeDependencies 和 build;

  • TestStatefulWidget 進(jìn)行二次 build ,因為父組件需要重新 build 觸發(fā)子組件的 didUpdateWidget ,didUpdateWidget 則觸發(fā) build。

為了驗證上面邏輯,我們現(xiàn)在再次點(diǎn)擊圖 3 中的紅色部分,來觸發(fā) TestStatefulWidget 組件的 build ,看下是否會觸發(fā)子組件的 didUpdateWidget 和 build。


image (9).png

圖 3 增加子組件界面點(diǎn)擊指示圖

在運(yùn)行日志窗口可以看到增加了下面的日志信息。

這就說明了父組件的變化會引發(fā)子組件的 build ,雖然子組件沒有任何的改動。這點(diǎn)如果是在前端的話,是需要使用 shouldUpdateComponent ,來介紹重新構(gòu)建,不過在 Flutter 中是沒有該功能來減少重新 build 的。

組件銷毀觸發(fā)

在上面的代碼基礎(chǔ)上,我們直接在 TestStatefulWidget 組件中注釋子組件 SubStatefulWidget 的調(diào)用,然后 熱重載 即可看到下面的日志信息(請注意一定是需要熱重載才會有效果,主要目的是一開始加載了該組件,后面再去掉該組件觸發(fā))。

綜合實踐

上一課時,只是簡單地顯示了一個時間,這里需要動態(tài)地顯示當(dāng)前的時間?;谖覀儽菊n時的學(xué)習(xí),我們需要實現(xiàn)以下幾點(diǎn):

  1. 使用有狀態(tài)組件來實現(xiàn),需要創(chuàng)建兩個類 StatefulWidget 和 State ,分別為 HomePage 和 HomePageState 對應(yīng)到一個文件 home_page.dart ;

  2. 定義一個當(dāng)前時間的 state currentTimeStr ,定義一個獲取當(dāng)前時間的函數(shù) getCurrentTime ,并在 initState 中調(diào)用一次該函數(shù)當(dāng)前時間;

  3. 實現(xiàn)函數(shù) getCurrentTime 獲取當(dāng)前時間;

  4. 定義并實現(xiàn)一個定時刷新的函數(shù) refreshTimeStr ,在定時函數(shù)中使用 Timer 定時使用 setState 來更新 state,并在 initState 中執(zhí)行該函數(shù);

  5. build 中展示當(dāng)前時間的 state 值,以及一個前綴信息;

接下來我們按照上面的步驟來實現(xiàn)代碼。

步驟一:創(chuàng)建有狀態(tài)類

使用有狀態(tài)組件來實現(xiàn),在 lib 的 pages 目錄下創(chuàng)建 home_page.dart ,接下來在文件中創(chuàng)建兩個類 StatefulWidget 和 State ,分別為 HomePage 和 HomePageState,代碼如下。

步驟二:增加狀態(tài)變量,實現(xiàn)初始化

定義一個當(dāng)前時間的 state currentTimeStr ,定義一個獲取當(dāng)前時間的函數(shù) getCurrentTime ,并在 initState 中調(diào)用一次該函數(shù)當(dāng)前時間,代碼如下。

步驟三:實現(xiàn) getCurrentTime 方法

實現(xiàn)函數(shù) getCurrentTime 獲取當(dāng)前時間,代碼如下。

步驟四:定時 Timer 實現(xiàn) state 定時更新

定義并實現(xiàn)一個定時刷新的函數(shù) refreshTimeStr ,在定時函數(shù)中使用 Timer 定時使用 setState 來更新 state,并在 initState 中執(zhí)行該函數(shù) ,代碼如下。

步驟五:build 中顯示組件內(nèi)容

build 中展示當(dāng)前時間的 state 值,以及一個前綴信息。由于前綴是一個無狀態(tài)變量,因此我們盡量將該變量放在 StatefulWidget 類中。這里在 build 中使用了一個新的布局組件 Column ,目前你暫時可以不關(guān)注這個組件,只需要了解其是布局組件即可,代碼如下。

步驟六:main.dart 中加載 HomPage 組件

最后我們需要在 main.dart 中應(yīng)用該組件,代碼如下。

步驟七:代碼美化和規(guī)范檢查,并運(yùn)行程序

現(xiàn)在我們將代碼實現(xiàn)完成了,需要使用我們 04 課時的知識來進(jìn)行美化代碼和檢查代碼是否規(guī)范,我們可以將美化和代碼規(guī)范檢查的兩個命令寫出一個 shell 腳本,每次只需要運(yùn)行這個 shell 腳本( format_check.sh )檢查即可,代碼如下。

接下來,每次運(yùn)行前執(zhí)行該腳本檢查。

檢查后,如果有問題則修復(fù),沒有問題,再選擇手機(jī)模擬器運(yùn)行該項目,既可以看到如下圖 2 動態(tài)效果了。


20200610_140500-2.gif

圖 2 增加動態(tài)時間顯示

總結(jié)

本課時主要介紹了組件中的有狀態(tài)組件和無狀態(tài)組件,關(guān)于有狀態(tài)組件則介紹了其各個生命周期函數(shù)的執(zhí)行場景以及實際觸發(fā)的應(yīng)用場景。最后再通過有狀態(tài)組件優(yōu)化我們之前的時間展示的小功能。學(xué)完本課時后,你需要掌握如何實現(xiàn)有狀態(tài)組件,并了解有狀態(tài)組件中各個生命周期函數(shù)被觸發(fā)的時機(jī)。

以上就是本課時的主要內(nèi)容,下一課時介紹有狀態(tài)組件和無狀態(tài)組件應(yīng)用場景,以及如何區(qū)分使用有狀態(tài)組件和無狀態(tài)組件。

點(diǎn)擊此鏈接查看本課時源碼: https://github.com/love-flutter/flutter-column

Flutter快學(xué)快用24講--06 生命周期:掌握 Flutter 生命周期以及應(yīng)用場景的評論 (共 條)

分享到微博請遵守國家法律
高陵县| 阿图什市| 丰顺县| 威宁| 白玉县| 五指山市| 汨罗市| 平和县| 唐河县| 博乐市| 威信县| 黑水县| 卢氏县| 祁东县| 义马市| 册亨县| 始兴县| 奈曼旗| 买车| 新源县| 柳江县| 溧阳市| 行唐县| 渝中区| 全州县| 林口县| 宜春市| 合水县| 宁德市| 丰宁| 汤阴县| 阿勒泰市| 福建省| 名山县| 灵丘县| 凭祥市| 涿州市| 中山市| 尼玛县| 娱乐| 右玉县|