四、Flutter之組件間通信

這里學(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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線程,因...
    小菜c閱讀 7,330評(píng)論 0 17
  • 原文在此,此處只為學(xué)習(xí) Widget與ElementWidget主要接口Stateless WidgetState...
    lltree閱讀 4,622評(píng)論 0 1
  • 1.App結(jié)構(gòu)和導(dǎo)航 Scaffold:Material Design布局結(jié)構(gòu)的基本實(shí)現(xiàn)。此類提供了用于顯示dra...
    慕容小偉閱讀 4,095評(píng)論 0 3
  • 第1步:創(chuàng)建初始Flutter應(yīng)用 創(chuàng)建一個(gè)簡(jiǎn)單的 Flutter 應(yīng)用。主要編輯 Dart 代碼所在的 lib ...
    小白_Sing閱讀 1,078評(píng)論 0 0
  • iOS程序的啟動(dòng)執(zhí)行順序 iOS程序的啟動(dòng)執(zhí)行順序 1 程序的入口 進(jìn)入main函數(shù), 設(shè)置AppDelegate...
    _Dam0n閱讀 935評(píng)論 0 1

友情鏈接更多精彩內(nèi)容