(六)flutter入門之widget解惑

首先在介紹flutter之前凡伊,我們需要了解一個(gè)概念,在dart中的理念是一切皆為對(duì)象窒舟,而在flutter上系忙,我們的理念是一切皆widget(可以理解為組件),flutter就是谷歌封裝的完善的基于MD風(fēng)格以及ios的Cupertino風(fēng)格的基于dart語(yǔ)言的一套u(yù)i組件框架惠豺,由于dart作為谷歌新系統(tǒng)的官方指定語(yǔ)言银还,并且為ios和安卓統(tǒng)一了開(kāi)發(fā)風(fēng)格,所以我們可以用flutter開(kāi)發(fā)出跨平臺(tái)的app洁墙,現(xiàn)在我們從widget開(kāi)始介紹flutter的組件

widget組件

在flutter中存在兩種widget蛹疯,一種是存在狀態(tài)改變的StatefulWidget 和無(wú)狀態(tài)改變的StatelessWidget ,這里的狀態(tài)是否需要改變對(duì)應(yīng)著我們開(kāi)發(fā)的過(guò)程中這個(gè)組件是否需要進(jìn)行動(dòng)態(tài)的ui更改操作扫俺,如果說(shuō)我們需要更改ui苍苞,這時(shí)候就需要繼承StatefulWidget 組件了,否則頁(yè)面就是個(gè)靜態(tài)的ui無(wú)法進(jìn)行更改,當(dāng)然在開(kāi)發(fā)的過(guò)程中羹呵,如果確定當(dāng)前頁(yè)面是靜態(tài)的骂际,推薦繼承StatelessWidget 組件,因?yàn)閷?duì)于flutter而言冈欢,靜態(tài)的頁(yè)面渲染的速度比動(dòng)態(tài)的組件要快一些歉铝,并且由于是靜態(tài)ui,渲染一次以后就不會(huì)進(jìn)行更改重新渲染凑耻,所以資源的消耗也會(huì)更小一些(當(dāng)然太示,如果怕出意外或者頻繁改動(dòng),所有的組件都繼承StatefulWidget 開(kāi)發(fā)香浩,也是可以的类缤,只是博主不推薦),現(xiàn)在我們創(chuàng)建一下這兩個(gè)不同的widget,看看到底有什么不同

StatelessWidget :

class MyStatelessWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
    );
  }
}

StatefulWidget :

class MyfulWidget extends StatefulWidget {
  @override
  _MyfulWidgetState createState() => _MyfulWidgetState();
}

class _MyfulWidgetState extends State<MyfulWidget> {
  @override
  Widget build(BuildContext context) {
    return Container(
    );
  }
}

從上面可以看出來(lái)邻吭,兩個(gè)widget都有build方法餐弱,這個(gè)build方法就是組件加載ui的方法,我們需要如何布局囱晴,組合出當(dāng)前的組件就需要在build方法中開(kāi)發(fā)膏蚓,唯一的區(qū)別就是build所在的類不同,StatelessWidget 的build方法就在自己的類中畸写,因?yàn)楫?dāng)前的組件是靜態(tài)組件驮瞧,只要加載渲染一次即可,所以默認(rèn)指定了ui布局枯芬,就不需要其他操作了论笔,但是StatefulWidget 的build是在createState的方法中創(chuàng)建的state子類中,這個(gè)state是flutter的概念破停,基本上所有的動(dòng)態(tài)的組件翅楼,谷歌的sdk中默認(rèn)都會(huì)指定對(duì)應(yīng)的State,而所有的ui加載也好真慢,數(shù)據(jù)變動(dòng)也好都在這個(gè)子類中操作毅臊,那么我們的ui需要變動(dòng)怎么辦呢?這個(gè)時(shí)候就需要一個(gè)方法手動(dòng)觸發(fā)更改黑界,刷新widget的生命周期(有React開(kāi)發(fā)經(jīng)驗(yàn)的應(yīng)該會(huì)發(fā)現(xiàn)這點(diǎn)flutter和React很相似管嬉,React也是靠綁定組件的狀態(tài),修改狀態(tài)來(lái)刷新ui的朗鸠,所以有經(jīng)驗(yàn)的童鞋蚯撩,可以按照React和原生安卓開(kāi)發(fā)的經(jīng)驗(yàn)來(lái)理解flutter的生命周期,會(huì)事半功倍)烛占,所以接下來(lái)我們學(xué)習(xí)一下widget的生命周期

1768723716-5b188ca549250_articlex.png

從上面可以看出來(lái)widget的生命周期大概分為三個(gè)階段

  • 初始化(插入渲染樹(shù))

  • 狀態(tài)改變(在渲染樹(shù)中存在)

  • 銷毀(從渲染樹(shù)種移除)

初始化階段

構(gòu)造函數(shù)
構(gòu)造函數(shù)屬于每個(gè)類的入口胎挎,肯定是widget的第一個(gè)方法沟启,一般我們都認(rèn)
為構(gòu)造函數(shù)不屬于生命周期的方法,只認(rèn)為是觸發(fā)生命周期的入口方法
initState
這個(gè)方法是widget的初始化方法犹菇,我們可以理解為原生安卓開(kāi)發(fā)的時(shí)候Activity的onCreate生命周期德迹,這
個(gè)方法在組件創(chuàng)建的時(shí)候只會(huì)觸發(fā)一次,我們可以在這個(gè)方法中調(diào)用一些參數(shù)的初始化操作揭芍,以及控制器的
一些監(jiān)聽(tīng)等胳搞,和我們?cè)_(kāi)發(fā)的習(xí)慣一樣,可以在這個(gè)方法中默認(rèn)initEvent()方法等其他操作称杨,但是不建
議在這里做耗時(shí)操作肌毅,否則會(huì)影響到組件的加載創(chuàng)建,甚至可能導(dǎo)致崩潰
didChangeDependencies
這個(gè)函數(shù)會(huì)緊接著在init函數(shù)之后調(diào)用姑原,并且可以調(diào)用并且可以調(diào)用BuildContext.inheritFromWidgetOfExactType悬而,
可能很多人會(huì)疑惑這BuildContext.inheritFromWidgetOfExactType有什么作用或者說(shuō)具體的場(chǎng)景是什么呢?
我們舉一個(gè)例子:假設(shè)我們有一個(gè)需求页衙,頁(yè)面上需要tab切換操作摊滔,tab一般需要自定義一個(gè)TabController,
但是tab有兩種用法店乐,還可以選擇使用默認(rèn)的DefaultTabController處理,這樣的話就不需要自定義控制器了呻袭,
在默認(rèn)的控制器中就用到了BuildContext.inheritFromWidgetOfExactType眨八,我們大概看下源碼:
void didChangeDependencies() {
    super.didChangeDependencies();
    _updateTabController();//從這里調(diào)用了BuildContext.inheritFromWidgetOfExactType
    _initIndicatorPainter();
  }

接著我們看看_updateTabController方法:

void _updateTabController() {
    final TabController newController = widget.controller ?? DefaultTabController.of(context);//這里涉及了一個(gè)of傳遞上下文的操作
    ...
    }

接下來(lái)我們看看這個(gè)傳遞上下文的方法

static TabController of(BuildContext context) {
    final _TabControllerScope scope = context.inheritFromWidgetOfExactType(_TabControllerScope);//就是這里觸發(fā)了BuildContext.inheritFromWidgetOfExactType
    return scope?.controller;
  }

看到了大概的源碼實(shí)現(xiàn),我們大概了解了這個(gè)didChangeDependencies生命周期的作用左电,但是有人會(huì)疑惑廉侧,BuildContext.inheritFromWidgetOfExactType到底有什么作用呢?這里我的看法是篓足,可以傳遞context使得組件之間可以跨組件獲取數(shù)據(jù)等操作(如果理解有誤或者有不同的看法,歡迎大佬指正)

build
這個(gè)生命周期我們一開(kāi)始也介紹了,用來(lái)掛載組件進(jìn)行最終ui布局渲染使用的两踏,但是由于我們可能存在ui
修改的情況授段,也就是說(shuō),這個(gè)函數(shù)不是只觸發(fā)一次的(是否觸發(fā)一次涩哟,是看是不是有state決定的索赏,不是當(dāng)前
生命周期決定)

狀態(tài)改變階段

didUpdateWidget
該生命周期一般是我們組件出現(xiàn)了狀態(tài)改變的時(shí)候,就會(huì)觸發(fā)當(dāng)前函數(shù)贴彼,在當(dāng)前函數(shù)中潜腻,flutter會(huì)創(chuàng)建出來(lái)
新的widget,然后和舊的狀態(tài)下的widget進(jìn)行比較器仗,看看有什么屬性不一樣融涣,有什么進(jìn)行了改變,然后重新
綁定,這個(gè)函數(shù)有個(gè)比較坑的點(diǎn)威鹿,比如我們改動(dòng)了以后妓盲,可能監(jiān)聽(tīng)的函數(shù)改變了,或者控制器變更了专普,我們
必須要在當(dāng)前方法進(jìn)行移除舊的控制器和監(jiān)聽(tīng)事件悯衬,然后重新綁定新的,否則會(huì)影響組件運(yùn)行檀夹,我們通過(guò)上
面的生命周期圖可以看出來(lái)筋粗,當(dāng)前函數(shù)調(diào)用完畢以后,就會(huì)再次調(diào)用build方法炸渡,也就是重新創(chuàng)建組件布局娜亿,
所以我們也可以確定每次我們修改完?duì)顟B(tài)后,flutter是重新創(chuàng)建widget出來(lái)

組件銷毀階段

deactivate
這個(gè)是在銷毀之前調(diào)用的生命周期蚌堵,目前具體的作用博主也沒(méi)使用過(guò)买决,不過(guò)經(jīng)過(guò)測(cè)試,當(dāng)前函數(shù)是在組件
還處于可見(jiàn)狀態(tài)下調(diào)用的吼畏,在dispose之前調(diào)用
dispose
組件調(diào)用到當(dāng)前函數(shù)的時(shí)候督赤,就會(huì)觸發(fā)真的移除組件,銷毀對(duì)象泻蚊,移除控制器躲舌,取消監(jiān)聽(tīng)事件等操作,
不過(guò)執(zhí)行當(dāng)前函數(shù)代表正在銷毀性雄,可以理解為還沒(méi)銷毀完畢没卸,當(dāng)前函數(shù)執(zhí)行完畢以后就是真的銷毀調(diào)用完畢

好了,經(jīng)過(guò)上面的生命周期講解秒旋,可能大概知道了widget的生命周期以及大概的作用约计,那么肯定有人會(huì)問(wèn),widget怎么觸發(fā)狀態(tài)改變呢迁筛?在widget中存在setState函數(shù)煤蚌,在這個(gè)函數(shù)內(nèi)部可以編寫我們需要改變的時(shí)候觸發(fā)的業(yè)務(wù)代碼,當(dāng)此方法調(diào)用的時(shí)候瑰煎,就代表著當(dāng)前的組件需要進(jìn)行狀態(tài)更改了铺然,即會(huì)觸發(fā)組件狀態(tài)改變階段生命周期流程,但是這里我們需要注意的一點(diǎn)是酒甸,在flutter中魄健,狀態(tài)改變的可能存在如下兩種

1.當(dāng)前組件內(nèi)部調(diào)用setState方法
2.當(dāng)前組件的父組件調(diào)用了setState方法,當(dāng)前的組件也會(huì)調(diào)用狀態(tài)改變重新渲染的流程插勤,孩子組件調(diào)用
狀態(tài)改變的方法并不會(huì)觸發(fā)父組件的狀態(tài)改變的方法(據(jù)說(shuō)新的sdk可能會(huì)改動(dòng)沽瘦,博主目前沒(méi)測(cè)試出來(lái))

其他特殊情況

注(博主在使用的過(guò)程中也遇到了很多其他的情況革骨,比如):
1.dispose 生命周期可能不會(huì)調(diào)用,在調(diào)用完deactivate 周期以后就掛載了新的節(jié)點(diǎn)到組件樹(shù)中的情況析恋。
2.didChangeDependencies生命周期一般情況下只有創(chuàng)建的時(shí)候會(huì)調(diào)用良哲,起初博主以為整個(gè)創(chuàng)建的周期的生命周期
都是只會(huì)調(diào)用一次,但是后來(lái)博主發(fā)現(xiàn)觸發(fā)了組件依賴的InheritedWidget改變的時(shí)候助隧,貌似也會(huì)觸發(fā)這個(gè)
生命周期筑凫,具體的原理應(yīng)該就是我們之前看BuildContext.inheritFromWidgetOfExactType有關(guān)。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末并村,一起剝皮案震驚了整個(gè)濱河市巍实,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌哩牍,老刑警劉巖棚潦,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異膝昆,居然都是意外死亡丸边,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門荚孵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)妹窖,“玉大人,你說(shuō)我怎么就攤上這事处窥≈雎穑” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵滔驾,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我俄讹,道長(zhǎng)哆致,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任患膛,我火速辦了婚禮摊阀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘踪蹬。我一直安慰自己胞此,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布跃捣。 她就那樣靜靜地躺著漱牵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪疚漆。 梳的紋絲不亂的頭發(fā)上酣胀,一...
    開(kāi)封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天刁赦,我揣著相機(jī)與錄音,去河邊找鬼闻镶。 笑死甚脉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的铆农。 我是一名探鬼主播牺氨,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼墩剖!你這毒婦竟也來(lái)了猴凹?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤涛碑,失蹤者是張志新(化名)和其女友劉穎精堕,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蒲障,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡歹篓,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了揉阎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片庄撮。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖毙籽,靈堂內(nèi)的尸體忽然破棺而出洞斯,到底是詐尸還是另有隱情,我是刑警寧澤坑赡,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布烙如,位于F島的核電站,受9級(jí)特大地震影響毅否,放射性物質(zhì)發(fā)生泄漏亚铁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一螟加、第九天 我趴在偏房一處隱蔽的房頂上張望徘溢。 院中可真熱鬧,春花似錦捆探、人聲如沸然爆。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)曾雕。三九已至,卻和暖如春雌隅,著一層夾襖步出監(jiān)牢的瞬間翻默,已是汗流浹背缸沃。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留修械,地道東北人趾牧。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像肯污,于是被迫代替她去往敵國(guó)和親翘单。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容