Flutter 之 數(shù)據(jù)傳遞

InheritedWidget 是 Flutter 中的一個功能型 Widget,適用于在 Widget 樹中共享數(shù)據(jù)的場景背稼。


class CounterPage extends StatefulWidget {

CounterPage({Key ? key}) :super(key: key);

@override

? _CounterPageState createState() =>_CounterPageState();

}

//

class _CounterPageState extends State {

int count =0;

//3我們通過 InheritedCountContainer.of 方法找到它衷恭,獲取計數(shù)狀態(tài) count 并展示:

? void _incrementCounter() => setState(() {count++;});// 修改計數(shù)器

? @override

? Widget build(BuildContext context) {

//2我們使用 CountContainer 作為根節(jié)點离福,并用 0 初始化 count谐岁。

? ? return CountContainer(

model:this,

increment: _incrementCounter,// 提供修改數(shù)據(jù)的方法

? ? ? ? child:Counter()

);

}

}

/*1

* 首先,為了使用 InheritedWidget贱纠,我們定義了一個繼承自它的新類 CountContainer。

* 然后响蕴,我們將計數(shù)器狀態(tài) count 屬性放到 CountContainer 中谆焊,

* 并提供了一個 of 方法方便其子 Widget 在 Widget 樹中找到它。

* 最后浦夷,我們重寫了 updateShouldNotify 方法辖试,這個方法會在 Flutter

*? 判斷 InheritedWidget 是否需要重建,從而通知下層觀察者組件更新數(shù)據(jù)時被調(diào)用到劈狐。

* 在這里罐孝,我們直接判斷 count 是否相等即可。

* */

class CountContainer extends InheritedWidget {

static CountContainer?of(BuildContext context) {

return context.dependOnInheritedWidgetOfExactType();

}

final _CounterPageState model;// 直接使用 MyHomePage 中的 State 獲取數(shù)據(jù)

? final Function()increment;

CountContainer({

Key ?key,

required this.model,

required this.increment,

required Widget child,

}):super(key: key, child: child);

@override

? bool updateShouldNotify(CountContainer oldWidget) =>model != oldWidget.model;

}

class Counter extends StatelessWidget {

@override

? Widget build(BuildContext context) {

// 獲取 InheritedWidget 節(jié)點

? ? CountContainer?state =CountContainer.of(context);

return Scaffold(

appBar:AppBar(

title:Text("InheritedWidget demo"),

),

body:Text(

'You have pushed the button this many times: ${state?.model.count}',// 關(guān)聯(lián)數(shù)據(jù)讀方法

? ? ? ),

floatingActionButton:FloatingActionButton(onPressed:state?.increment),// 關(guān)聯(lián)數(shù)據(jù)修改方法

? ? );

}

}

Notification 是 Flutter 中進行跨層數(shù)據(jù)共享的另一個重要的機制肥缔。如果說 InheritedWidget 的數(shù)據(jù)流動方式是從父 Widget 到子 Widget 逐層傳遞莲兢,那 Notificaiton 則恰恰相反,數(shù)據(jù)流動方式是從子 Widget 向上傳遞至父 Widget续膳。這樣的數(shù)據(jù)傳遞機制適用于子 Widget 狀態(tài)變更怒见,發(fā)送通知上報的場景。

class CustomNotification extends Notification {

CustomNotification(this.msg);

final String msg;

}

class CustomChild extends StatelessWidget {

@override

? Widget build(BuildContext context) {

return RaisedButton(

//按鈕點擊時分發(fā)通知

? ? ? onPressed: () =>CustomNotification("Hi").dispatch(context),

child:Text("Fire Notification"),

);

}

}

class NotificationWidget extends StatefulWidget {

@override

? StatecreateState()=>_NotificationState();

}

class _NotificationState extends State {

String _msg ="通知:";

@override

? Widget build(BuildContext context) {

//監(jiān)聽通知

? ? return NotificationListener(

onNotification: ( notification) {

setState(() {_msg += notification.msg+"? ";});

return true;

},

child:Column(

mainAxisAlignment:MainAxisAlignment.center,

children: [Text(_msg),CustomChild()],

)

);

}

}

無論是 InheritedWidget 還是 Notificaiton姑宽,它們的使用場景都需要依靠 Widget 樹遣耍,也就意味著只能在有父子關(guān)系的 Widget 之間進行數(shù)據(jù)共享。但是炮车,組件間數(shù)據(jù)傳遞還有一種常見場景:這些組件間不存在父子關(guān)系舵变。這時,事件總線 EventBus 就登場了瘦穆。

事件總線是在 Flutter 中實現(xiàn)跨組件通信的機制纪隙。它遵循發(fā)布 / 訂閱模式,允許訂閱者訂閱事件扛或,當(dāng)發(fā)布者觸發(fā)事件時绵咱,訂閱者和發(fā)布者之間可以通過事件進行交互。發(fā)布者和訂閱者之間無需有父子關(guān)系熙兔,甚至非 Widget 對象也可以發(fā)布 / 訂閱悲伶。

// 所以在這里艾恼,我們傳輸數(shù)據(jù)的載體就選擇了一個有字符串屬性的自定義事件類 CustomEvent:

class CustomEvent {

String msg;

CustomEvent(this.msg);

}

// 建立公共的 event bus

EventBus eventBus =new EventBus();

/*

* 我們定義了一個全局的 eventBus 對象,并在第一個頁面監(jiān)聽了 CustomEvent 事件麸锉,

* 一旦收到事件钠绍,就會刷新 UI。

* 需要注意的是花沉,千萬別忘了在 State 被銷毀時清理掉事件注冊柳爽,

* 否則你會發(fā)現(xiàn) State 永遠被 EventBus 持有著,無法釋放碱屁,從而造成內(nèi)存泄漏:

*

*? */

class FirstPage extends StatefulWidget {

@override

? StatecreateState()=>_FirstPageState();

}

class _FirstPageState extends State {

String msg ="通知:";

late StreamSubscription subscription;

@override

? void initState() {

//監(jiān)聽CustomEvent事件磷脯,刷新UI

? ? subscription =eventBus.on().listen((event) {

print(event.msg);

setState(() {

msg += event.msg;

});

});

super.initState();

}

dispose() {

subscription.cancel();//State銷毀時,清理注冊

? ? super.dispose();

}

@override

? Widget build(BuildContext context) {

return Scaffold(

appBar:AppBar(title:Text("First Page"),),

body:Text(msg),

floatingActionButton:FloatingActionButton(onPressed: ()=>Navigator.push(context,MaterialPageRoute(builder: (context) =>SecondPage()))),

);

}

}

//我們在第二個頁面以按鈕點擊回調(diào)的方式娩脾,觸發(fā)了 CustomEvent 事件:

class SecondPage extends StatelessWidget {

Widget build(BuildContext context) {

return Scaffold(

appBar:AppBar(title:Text("Second Page"),),

body:RaisedButton(

child:Text('Fire Event'),

// 觸發(fā)CustomEvent事件

? ? ? ? ? onPressed: ()=>eventBus.fire(CustomEvent("hello"))

),

);

}

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末争拐,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子晦雨,更是在濱河造成了極大的恐慌架曹,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件闹瞧,死亡現(xiàn)場離奇詭異绑雄,居然都是意外死亡,警方通過查閱死者的電腦和手機奥邮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門万牺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人洽腺,你說我怎么就攤上這事脚粟。” “怎么了蘸朋?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵核无,是天一觀的道長。 經(jīng)常有香客問我藕坯,道長团南,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任炼彪,我火速辦了婚禮吐根,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘辐马。我一直安慰自己拷橘,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著冗疮,像睡著了一般萄唇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赌厅,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機與錄音轿塔,去河邊找鬼特愿。 笑死,一個胖子當(dāng)著我的面吹牛勾缭,可吹牛的內(nèi)容都是我干的揍障。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼俩由,長吁一口氣:“原來是場噩夢啊……” “哼毒嫡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起幻梯,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤兜畸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后碘梢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體咬摇,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年煞躬,在試婚紗的時候發(fā)現(xiàn)自己被綠了肛鹏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡恩沛,死狀恐怖在扰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情雷客,我是刑警寧澤芒珠,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站搅裙,受9級特大地震影響妓局,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜呈宇,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一好爬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧甥啄,春花似錦存炮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宫盔。三九已至,卻和暖如春享完,著一層夾襖步出監(jiān)牢的瞬間灼芭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工般又, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留彼绷,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓茴迁,卻偏偏與公主長得像寄悯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子堕义,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353

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