Flutter中跨組件數(shù)據(jù)傳遞的方法總結(jié)
方法1:InheritedWidget
InheritedWidget:它提供了一種數(shù)據(jù)在Widget樹中從上向下傳遞,共享的方式。我們?cè)趹?yīng)用的根Widget中通過InheritedWidget共享了一個(gè)數(shù)據(jù),那么我們可以在任意子Widget中獲取該共享的數(shù)據(jù)!其通用方式就是:
class ShareDataWidget extends InheritedWidget {
final int data;
ShareDataWidget({this.data, Widget child}) : super(child: child);
static ShareDataWidget of(BuildContext context){
return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();
}
@override
bool updateShouldNotify(ShareDataWidget oldWidget) {
return oldWidget.data !=data;
}
}其實(shí)就是繼承InheritedWidget,首先定義需要保存的數(shù)據(jù)比如這里的int型data,然后實(shí)現(xiàn)updateShouldNotify方法,最后定義一個(gè)獲取該Widget的靜態(tài)方法,在需要使用該保存數(shù)據(jù)的時(shí)候通過這個(gè)靜態(tài)方法獲取。使用時(shí),在父widget中傳入需要保存的data,在child中通過定義的靜態(tài)方法來獲取最新值。比如定義的parent如下
class Parent extends StatefulWidget {
Parent({Key key}) : super(key: key);
_ParentState createState() => _ParentState();
}
class _ParentState extends State<Parent> with WidgetsBindingObserver {
int _counter = 0;
//當(dāng)Widget第一次插入到Widget樹時(shí)會(huì)被調(diào)用。對(duì)于每一個(gè)State對(duì)象,F(xiàn)lutter只會(huì)調(diào)用該回調(diào)一次
@override
void initState() {
super.initState();
print("page2 parent initState......");
}
@override
void setState(fn) {
super.setState(fn);
print("page2 parent setState......");
}
/*
*初始化時(shí),在initState之后立刻調(diào)用
*當(dāng)State的依賴關(guān)系發(fā)生變化時(shí),會(huì)觸發(fā)此接口被調(diào)用
*/
@override
void didChangeDependencies() {
super.didChangeDependencies();
print("page2 parent didChangeDependencies......");
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
print("page2 state is $state");
}
//繪制界面
@override
Widget build(BuildContext context) {
print("page2 parent build......");
return Scaffold(
appBar: AppBar(title: Text("setState demo")),
body: Center(
child: ShareDataWidget(
data: _counter,
child: RaisedButton(
///點(diǎn)擊事件
onPressed: () {
setState(() {
_counter++;
});
},
child: Child(),
),
)),
);
}
//狀態(tài)改變的時(shí)候會(huì)調(diào)用該方法,比如父類調(diào)用了setState
@override
void didUpdateWidget(Parent oldWidget) {
super.didUpdateWidget(oldWidget);
print("page2 parent didUpdateWidget......");
}
//當(dāng)State對(duì)象從樹中被移除時(shí),會(huì)調(diào)用此回調(diào)
@override
void deactivate() {
super.deactivate();
print('page2 parent deactivate......');
}
//當(dāng)State對(duì)象從樹中被永久移除時(shí)調(diào)用;通常在此回調(diào)中釋放資源
@override
void dispose() {
super.dispose();
print('page2 parent dispose......');
}
}可以看到我們傳入了_counter屬性到ShareDataWidget中,并且SharedDataWidget的child需要使用共享的變量。我們的Child定義如下
class Child extends StatefulWidget {
Child({Key key}) : super(key: key);
@override
_ChildState createState() => _ChildState();
}
class _ChildState extends State<Child> {
//繪制界面
@override
Widget build(BuildContext context) {
print("child build......");
return Text.rich(TextSpan(children: [
TextSpan(
text: '點(diǎn)擊按鈕查看狀態(tài)變化 count: ${ShareDataWidget.of(context).data.toString()}',
style: TextStyle(color: Color.fromARGB(100, 255, 0, 0))),
TextSpan(
text: "新加的一段文本",
style: TextStyle(color: Colors.blue),
recognizer: TapGestureRecognizer()
..onTap = () {
print("點(diǎn)擊了文本");
})
]));
}
//當(dāng)Widget第一次插入到Widget樹時(shí)會(huì)被調(diào)用。對(duì)于每一個(gè)State對(duì)象,F(xiàn)lutter只會(huì)調(diào)用該回調(diào)一次
@override
void initState() {
super.initState();
print("page2 child initState......");
}
/*
*初始化時(shí),在initState之后立刻調(diào)用
*當(dāng)State的依賴關(guān)系發(fā)生變化時(shí),會(huì)觸發(fā)此接口被調(diào)用
*/
@override
void didChangeDependencies() {
super.didChangeDependencies();
print("page2 child didChangeDependencies......");
}
//狀態(tài)改變的時(shí)候會(huì)調(diào)用該方法,比如父類調(diào)用了setState
@override
void didUpdateWidget(Child oldWidget) {
super.didUpdateWidget(oldWidget);
print("page2 child didUpdateWidget......");
}
//當(dāng)State對(duì)象從樹中被移除時(shí),會(huì)調(diào)用此回調(diào)
@override
void deactivate() {
super.deactivate();
print('page2 child deactivate......');
}
//當(dāng)State對(duì)象從樹中被永久移除時(shí)調(diào)用;通常在此回調(diào)中釋放資源
@override
void dispose() {
super.dispose();
print('page2 child dispose......');
}
}其使用就是在Parent中用創(chuàng)建好的ShareDataWidget作為父Widget,在父widget更新需要保存的變量時(shí),同時(shí)將數(shù)據(jù)保存在ShareDataWidget的data中,比如上面在parent的build方法中

真正使用這個(gè)值的地方是Child類,它的build方法

在parent中觸發(fā)onPress事件其調(diào)用如下

通過使用方式可以看到明顯適用于父->子
方法2:Notification
Notification它的數(shù)據(jù)傳遞方式是從子Widget向上傳遞給父Widget。比如先定義一個(gè)notification,這里只有一個(gè)msg需要傳遞給父Widget。
class CustomNotification extends Notification{
final String msg;
CustomNotification(this.msg);
}然后定義一個(gè)子Widget來發(fā)送這個(gè)通知
class CustomChild extends StatelessWidget{
@override
Widget build(BuildContext context) {
return ElevatedButton(onPressed: ()=>CustomNotification("HI").dispatch(context),child: Text("FireNotification"),);
}
}在父widget中使用這個(gè)通知
class ParentPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _ParentPageState();
}
}
class _ParentPageState extends State<ParentPage> {
String msg = "通知";
@override
Widget build(BuildContext context) {
return NotificationListener<CustomNotification>(
onNotification: (notification){
setState(() {
msg+=notification.msg+" ";
});
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [Text(msg), CustomChild()],
));
}
}可以看到父widget中的根是NotificationListener這個(gè)監(jiān)聽器,剛才定義的CustomChild是他的子Widget。
方法3:EventBus
這種方式在Android中也經(jīng)常使用,這個(gè)就比較簡(jiǎn)單了。首先引用該組件event_bus: ^2.0.0??梢栽谌致暶饕粋€(gè)EventBus實(shí)例,比如在main.dart中。
EventBus bus = new EventBus();
在需要接收訂閱的類中
StreamSubscription subscription;
String msg = "event Msg";
//當(dāng)Widget第一次插入到Widget樹時(shí)會(huì)被調(diào)用。對(duì)于每一個(gè)State對(duì)象,F(xiàn)lutter只會(huì)調(diào)用該回調(diào)一次
@override
void initState() {
subscription = bus.on<CustomEvent>().listen((event) {
setState(() {
msg+=event.msg+" ";
});
});
super.initState();
print("page1 initState......");
}這里的subscription其實(shí)就是為了防止泄露的,在dispose的時(shí)候我們要解除訂閱,CustomEvent其實(shí)就是一個(gè)類,
class CustomEvent{
String msg;
CustomEvent(this.msg);
}在需要發(fā)送通知的地方
bus.fire(CustomEvent("我是EventBus發(fā)送的"));這個(gè)比較適合于父->父。也就是所謂的“頁面間”的數(shù)據(jù)傳遞
以上就是Flutter中跨組件數(shù)據(jù)傳遞的方法總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Flutter數(shù)據(jù)傳遞的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android 實(shí)現(xiàn)仿網(wǎng)絡(luò)直播彈幕功能詳解及實(shí)例
這篇文章主要介紹了Android 實(shí)現(xiàn)仿網(wǎng)絡(luò)直播彈幕功能詳解的相關(guān)資料,并附實(shí)例代碼及實(shí)現(xiàn)效果圖,需要的朋友可以參考下2016-11-11
Android 邊播邊緩存的實(shí)現(xiàn)(MP4 未加密m3u8)
這篇文章主要介紹了Android 邊播邊緩存的實(shí)現(xiàn)(MP4 未加密m3u8),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
Android開發(fā)中synchronized的三種使用方式詳解
這篇文章主要介紹了Android開發(fā)中synchronized的三種使用方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-04-04
Android APP開發(fā)KML軌跡導(dǎo)出教程示例
這篇文章主要為大家介紹了Android APP開發(fā)KML軌跡導(dǎo)出教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Android的Activity跳轉(zhuǎn)動(dòng)畫各種效果整理
Android的Activity跳轉(zhuǎn)就是很生硬的切換界面。其實(shí)Android的Activity跳轉(zhuǎn)可以設(shè)置各種動(dòng)畫,本文整理了一些,還有很多動(dòng)畫效果,就要靠我們發(fā)揮自己的想象力2013-06-06
Android中ViewPager的PagerTabStrip與PagerTitleStrip用法實(shí)例
這篇文章主要介紹了Android中ViewPager的PagerTabStrip與PagerTitleStrip用法實(shí)例,這兩個(gè)子控件一般被用作添加標(biāo)題,在實(shí)際效果上并不是那么好控制,使用的時(shí)候需要謹(jǐn)慎,需要的朋友可以參考下2016-06-06
Android 自定義View實(shí)現(xiàn)多節(jié)點(diǎn)進(jìn)度條功能
這篇文章主要介紹了Android 自定義View實(shí)現(xiàn)多節(jié)點(diǎn)進(jìn)度條,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05
react native android6+拍照閃退或重啟的解決方案
android 6+權(quán)限使用的時(shí)候需要?jiǎng)討B(tài)申請(qǐng),那么在使用rn的時(shí)候要怎么處理拍照權(quán)限問題呢?本文提供的是一攬子rn操作相冊(cè)、拍照的解決方案,需要的朋友可以參考下2017-11-11

