這里學(xué)了兩種通信方式,一種是回調(diào)、另一種是借用第三方庫(kù)event_bus,其他的還有GlobalKey、ValueNotifier、Redux等,后續(xù)再研究。
一、回調(diào)
組件間通信可以用回調(diào)方式,這里不需要像java新建一個(gè)接口類再實(shí)現(xiàn),Dart是支持把方法作為對(duì)象傳遞的,也就是說(shuō)可以直接把需要回調(diào)的方法作為變量傳給目標(biāo)。
/**
* 父子、兄弟組件通信
*/
class WidgetContactDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Material(
child: new Scaffold(
appBar: new AppBar(
title: new Text("組件間通信"),
),
//主體
body: new ParentWidget(),
));
}
}
//父組件
class ParentWidget extends StatefulWidget {
@override
State createState() {
return _ParentWidget();
}
}
class _ParentWidget extends State<ParentWidget> {
var bgColor; //父組件背景色
var btnColor; //子組件背景色
changeParentColor(color) {
setState(() {
bgColor = color;
});
}
changeButtonColor() {
setState(() {
btnColor = RandomColor().get();
});
}
@override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
color: bgColor,
child: Column(
children: <Widget>[
RaisedButton(
onPressed: changeButtonColor,
child: Text('Button1,點(diǎn)擊修改button2背景色'),
),
//這里把方法changeParentColor和變量btnColor傳入MyButton,如果changeParentColor是無(wú)參函數(shù),可以直接用MyButton(changeParentColor,btnColor),
MyButton((c) => changeParentColor(c), btnColor),
],
),
);
}
}
//子組件按鈕,需要傳入一個(gè)點(diǎn)擊事件callback和一個(gè)背景色btnColor,點(diǎn)擊時(shí)會(huì)調(diào)用callback,而btnColor在外部修改的時(shí)候,子組件也會(huì)響應(yīng)修改。
class MyButton extends StatefulWidget {
Function callback;
var btnColor;
//dart構(gòu)造函數(shù),可以直接把傳入?yún)?shù)賦值給相應(yīng)變量
MyButton(this.callback, this.btnColor);
//下面這種寫法的構(gòu)造函數(shù)支持MyButton(callback:(c)=>changeParentColor(c),btnColor:btnColor),
// MyButton({Key key,this.callback,this.btnColor}) : super(key:key) ;
@override
State createState() {
return _MyButton();
}
}
class _MyButton extends State<MyButton> {
@override
Widget build(BuildContext context) {
return RaisedButton(
//State里可以通過(guò)widget訪問(wèn)其StatefulWidget里的變量,此處常見(jiàn)錯(cuò)誤!不能寫作widget.callback(Colors.black12)
onPressed: () => widget.callback(RandomColor().get()),
child: Text('Button2,點(diǎn)擊修改父控件背景色'),
color: widget.btnColor,
);
}
}
//隨機(jī)顏色類
class RandomColor {
final bgColors = [
Colors.white,
Colors.yellow,
Colors.orange,
Colors.cyan,
Colors.lime,
Colors.pinkAccent
];
Color get() {
return bgColors[Random.secure().nextInt(bgColors.length)];
}
}
這段代碼實(shí)現(xiàn)了點(diǎn)擊button1修改button2的顏色,點(diǎn)擊button2修改parent的顏色,代碼中的new關(guān)鍵字都省略了,這是dart2中的新特性。
從外部修改button2的顏色比較簡(jiǎn)單,只要在button1點(diǎn)擊事件中修改傳入button2的變量btnColor即可;
從button2點(diǎn)擊修改父組件顏色,就需要用到回調(diào),父控件構(gòu)建button2的時(shí)候傳入回調(diào)函數(shù)MyButton((c) => changeParentColor(c), btnColor),這里changeParentColor是作為一個(gè)對(duì)象之間傳入子控件賦值給callback的,而子控件在onPressed: () => widget.callback(RandomColor().get()),這里設(shè)置了點(diǎn)擊事件,點(diǎn)擊時(shí)調(diào)用widget.callback即changeParentColor,以達(dá)到從內(nèi)部向外部通信的目的,注意不能寫成onPressed:widget.callback(RandomColor().get())
二、eventbus
先在pubspec.yaml里增加依賴
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
event_bus: ^1.0.1//增加依賴
dart文件中再導(dǎo)入包
import 'package:event_bus/event_bus.dart';
接下來(lái)就可以使用eventbus進(jìn)行通信了,下面代碼實(shí)現(xiàn)了點(diǎn)擊button3可以修改button4的顏色,也就是點(diǎn)擊的時(shí)發(fā)送一個(gè)事件,button4監(jiān)聽(tīng)到該事件就改變自身顏色。
/**
* 以下是用eventbus進(jìn)行通信
*/
EventBus eventBus = new EventBus();
//新建修改顏色的事件
class ColorEvent{
Color color;
ColorEvent(this.color);
}
//button3
class MyButton3 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RaisedButton(
//點(diǎn)擊的時(shí)候發(fā)送改變顏色事件
onPressed: () => eventBus.fire(ColorEvent(RandomColor().get())),
child: Text('Button3,點(diǎn)擊修改Button4顏色'),
);
}
}
//button4
class MyButton4 extends StatefulWidget {
@override
State createState() {
return _MyButton4();
}
}
class _MyButton4 extends State<MyButton4> {
Color bgColor;
@override
void initState() {
//注冊(cè)eventBus事件,監(jiān)聽(tīng)到變化的時(shí)候調(diào)用changeColor(color)
eventBus.on<ColorEvent>().listen((ColorEvent data) => changeColor(data.color));
super.initState();
}
changeColor(color){
//若不對(duì)mounted進(jìn)行判斷,會(huì)報(bào)錯(cuò) setState() called after dispose()
if(mounted){
setState(() {
bgColor=color;
});
}
}
@override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: ()=>{},//必須給onPressed一個(gè)空方法,不能是null,否則無(wú)法修改color屬性
child: Text('Button4'),
color: bgColor,
);
}
}
eventbus的Git地址:https://github.com/marcojakob/dart-event-bus
詳解可參考:https://cloud.tencent.com/developer/article/1338289