一,概述 

   flutter一个重要的特性就是组件化。组件分为两种状态,一种是StatefulWidget有状态组件,一种是StatelessWidget无状态组件。 无状态组件不能更新状态,有状态组件具有类似刷新的机制,可更改状态。
  功能模块都可以通过继承两种状态组件实现功能模块封装。组件间通信,一般存在一下两种关系。

      • 父子组件通信
      • 兄弟组件通信       

二, 通信实现方式

  • 回调通信

    • 需求“点击子组件,修改父组件的背景颜色与子组件背景颜色一致”
    • 代码实现
      //父组件
      
      class ParentWidget extends StatefulWidget {
      final String title;
      ParentWidget({Key key,this.title}):super(key:key); @override
      State<StatefulWidget> createState() {
      return new ParentWidgetState();
      }
      } class ParentWidgetState extends State<ParentWidget> {
      Color containerBg = Colors.orange;
      //回调函数
      void changeBackgroundColor(Color newColor){
      setState(() {
      containerBg = newColor;//修改状态
      });
      } @override
      Widget build(BuildContext context) {
      return new Scaffold(
      appBar: new AppBar(
      title: new Text(widget.title),
      ),
      body: new Center(
      child: new GestureDetector(
      onTap: (){
      changeBackgroundColor(Colors.orange);
      },
      child: new Container(
      width: 300,
      height: 300,
      color: containerBg,
      alignment: Alignment.center,
      child: new Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: <Widget>[
      new childrenA(childrenACallBack: changeBackgroundColor),
      new childrenB(childrenBCallBack: changeBackgroundColor),
      ],
      ),
      ),
      )
      ),
      );
      }
      } //子组件(组件A)
      class childrenA extends StatelessWidget {
      //定义接收父类回调函数的指针
      final ValueChanged<Color> childrenACallBack;
      childrenA({Key key,this.childrenACallBack}):super(key:key);
        @override
      Widget build(BuildContext context) {
      return new GestureDetector(
      onTap: (){
         //调用回调函数传值
      childrenACallBack(Colors.green);
      },
      child: new Container(
      width: 80,
      height: 80,
      color: Colors.green,
      child: new Text('ChildrenA'),
      ),
      );
      }
      } //子组件(组件B)
      class childrenB extends StatelessWidget {
      final ValueChanged<Color> childrenBCallBack;
      childrenB({Key key,this.childrenBCallBack}):super(key:key); @override
      Widget build(BuildContext context) {
      return new GestureDetector(
      onTap:(){
      childrenBCallBack(Colors.red);
      },
      child: new Container(
      width: 80,
      height: 80,
      color: Colors.red,
      child: new Text('ChildredB'),
      ),
      );
      }
      }
    • 功能实现

    • 使用场景:一般用于子组件对父组件传值。
  • InheritedWidget 数据共享

    • 场景:业务开发中经常会碰到这样的情况,多个Widget需要同步同一份全局数据,比如点赞数、评论数、夜间模式等等。
    • 代码实现:
      import 'package:flutter/material.dart';
      
      void main() => runApp(MyApp());
      
      class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
      return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
      primarySwatch: Colors.blue, ),
      home: new InheritedWidgetTestContainer(),
      );
      }
      } //模型数据
      class InheritedTestModel {
      final int count;
      const InheritedTestModel(this.count);
      } //哨所(自定义InheritedWidget类)
      class InheritedContext extends InheritedWidget {
      //构造函数
      InheritedContext({
      Key key,
      @required this.inheritedTestModel,
      @required this.increment,
      @required this.reduce,
      @required Widget child
      }):super(key:key,child:child); //变量
      final InheritedTestModel inheritedTestModel;
      final Function() increment;
      final Function() reduce; //静态方法
      static InheritedContext of(BuildContext context){
      InheritedContext contexts = context.inheritFromWidgetOfExactType(InheritedContext);
      return context.inheritFromWidgetOfExactType(InheritedContext);
      }
      //是否重建取决于Widget组件是否相同
      @override
      bool updateShouldNotify(InheritedContext oldWidget) {
      return inheritedTestModel != oldWidget.inheritedTestModel;
      }
      } class TestWidgetA extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
      final inheritedContext = InheritedContext.of(context);
      return new Padding(
      padding: const EdgeInsets.only(left: 10.0,top: 10.0,right: 10.0),
      child: new RaisedButton(
      textColor: Colors.black,
      child: new Text('+'),
      onPressed:inheritedContext.increment
      ),
      );
      }
      } class TestWidgetB extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
      final inheritedContext = InheritedContext.of(context);
      return new Padding(
      padding: const EdgeInsets.only(left: 10,top: 10,right: 10.0),
      child: new RaisedButton(
      textColor: Colors.black,
      child: new Text('-'),
      onPressed: inheritedContext.reduce
      ),
      );
      }
      } class TestWidgetC extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
      final inheritedContext = InheritedContext.of(context);
      final inheritedTestModel = inheritedContext.inheritedTestModel; return new Padding(
      padding: const EdgeInsets.only(left: 10.0,top: 10.0,right: 10.0),
      child: new RaisedButton(
      textColor: Colors.black,
      child: new Text('${inheritedTestModel.count}'),
      onPressed: (){ },
      ),
      );
      }
      } class InheritedWidgetTestContainer extends StatefulWidget {
      @override
      State<StatefulWidget> createState() {
      return new InheritedWidgetTestContainerState();
      }
      } class InheritedWidgetTestContainerState extends State<InheritedWidgetTestContainer> { InheritedTestModel _inheritedTestModel; _initData(){
      _inheritedTestModel = new InheritedTestModel(0);
      } @override
      void initState() {
      _initData();
      super.initState();
      } _incrementCount(){
      setState(() {
      _inheritedTestModel = new InheritedTestModel(_inheritedTestModel.count + 1);
      });
      } _reduceCount(){
      setState(() {
      _inheritedTestModel = new InheritedTestModel(_inheritedTestModel.count - 1);
      });
      } @override
      Widget build(BuildContext context) {
      return new InheritedContext(
      inheritedTestModel: _inheritedTestModel,
      increment: _incrementCount,
      reduce: _reduceCount,
      child: new Scaffold(
      appBar: new AppBar(
      title: new Text('InheritedWidgetTest'),
      ),
      body: new Center(
      child: new Column(
      children: <Widget>[
      new TestWidgetA(),
      new TestWidgetB(),
      new TestWidgetC(),
      ],
      ),
      )
      ),
      );
      }
      }
    • 功能实现
       
    • 使用场景
      一般用于父组件对子组件的跨组件传值。

  • Global Key通信
    GlobalKey能够跨Widget访问状态。
    • 需求“点击A子组件,修改B子组件的背景颜色为指定的‘蓝色”
    • 代码实现
      //父组件
      class ParentWidget extends StatefulWidget {
      @override
      State<StatefulWidget> createState() {
      return new ParentWidgetState();
      }
      } class ParentWidgetState extends State<ParentWidget> {
      @override
      Widget build(BuildContext context) { return new Scaffold(
      appBar: new AppBar(
      title: new Text('组件化'),
      ),
      body: new Center(
      child: new Container(
      color: Colors.grey,
      width: 200,
      height: 200,
      child: new Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: <Widget>[
      new SubWidgetA(key: subAkey),
      new SubWidgetB(key: subBkey)
      ],
      ),
      ),
      ),
      );
      }
      } //子组件A class SubWidgetA extends StatefulWidget {
      SubWidgetA({Key key}):super(key:key);
      @override
      State<StatefulWidget> createState() {
      return new SubWidgetAState();
      }
      } class SubWidgetAState extends State <SubWidgetA> { Color _backgroundColors = Colors.red;//红色
      void updateBackGroundColors(Color colos){
      setState(() {
      _backgroundColors = colos;
      });
      } @override
      Widget build(BuildContext context) {
      return new GestureDetector(
      onTap: (){
      subBkey.currentState.updateBackGroundColors(Colors.blue);
      setState(() {
      _backgroundColors = Colors.red;
      });
      },
      child: new Container(
      width: 80,
      height: 80,
      color:_backgroundColors,
      alignment: Alignment.center,
      child: new Text('SubWidgetA'),
      ),
      );
      }
      } //子组件B
      class SubWidgetB extends StatefulWidget {
      SubWidgetB({Key key}):super(key:key);
      @override
      State<StatefulWidget> createState() {
      // TODO: implement createState
      return new SubWidgetBState();
      }
      } class SubWidgetBState extends State<SubWidgetB> { Color _backgroundColors = Colors.green;//绿色
      void updateBackGroundColors(Color colos){
      setState(() {
      _backgroundColors = colos;
      });
      } @override
      Widget build(BuildContext context) {
      return new GestureDetector(
      onTap: (){
      subAkey.currentState.updateBackGroundColors(Colors.blue);
      setState(() {
      _backgroundColors = Colors.green;
      }); },
      child: new Container(
      width: 80,
      height: 80,
      color: _backgroundColors,
      alignment: Alignment.center,
      child: new Text('SubWidgetB'),
      ),
      );
      }
      }
    • 功能实现
    • 使用场景:一般用于跨组件访问状态
  • ValueNotifier通信 

     ValueNotifier是一个包含单个值的变更通知器,当它的值改变的时候,会通知它的监听。

    1. 定义ValueNotifierData类,继承ValueNotifier

      class ValueNotifierData extends ValueNotifier<String> {
      ValueNotifierData(value) : super(value);
      }
    1. 定义_WidgetOne,包含一个ValueNotifierData的实例。

      class _WidgetOne extends StatefulWidget {
      _WidgetOne({this.data});
      final ValueNotifierData data;
      @override
      _WidgetOneState createState() => _WidgetOneState();
      }
    1. _WidgetOneState中给ValueNotifierData实例添加监听。

      @override
      initState() {
      super.initState();
      widget.data.addListener(_handleValueChanged);
      info = 'Initial mesage: ' + widget.data.value;
      } void _handleValueChanged() {
      setState(() {
      info = 'Message changed to: ' + widget.data.value;
      });
    1. ValueNotifierCommunication组件中实例化_WidgetOne,可以通过改变ValueNotifierData实例的value来触发_WidgetOneState的更新。

      @override
      Widget build(BuildContext context) {
      ValueNotifierData vd = ValueNotifierData('Hello World');
      return Scaffold(
      appBar: AppBar(title: Text('Value Notifier Communication'),),
      body: _WidgetOne(data: vd),
      floatingActionButton: FloatingActionButton(child: Icon(Icons.refresh),onPressed: () {
      vd.value = 'Yes';
      }),
      );
      }
  • 第三方插件
      在这里运用event_bus来实现传值,用于组件与组件之间的传值。
    • event_bus 

      • 引入插件

        import 'package:event_bus/event_bus.dart';
      • event_bus用法。

        • 新建消息监测类

          import 'package:event_bus/event_bus.dart';
          EventBus eventBus = new EventBus();
          class TransEvent{
          String text;
          TransEvent(this.text);
          }
        • 监测类变化

          eventBus.on<TransEvent>().listen((TransEvent data) => show(data.text));
          void show(String val) {
          setState(() {
          data = val;
          });
          }
        • 触发消息变化

          eventBus.fire(new TransEvent('$inputText'));
      • 使用场景:这样我们就可以根据这些来实现组件之间的传值。

最新文章

  1. Page
  2. js学习笔记6----作用域及解析机制
  3. 九 spring和mybatis整合
  4. phpStorm如何在Console控制台执行php文本,而不是浏览器中
  5. 二分法查找(Binary Search)
  6. Android新建项目 默认布局改为 LinearLayout
  7. php汉字转Unicode编码函数
  8. Windows Server2012R2 添加Microsoft .NET Framework 3.5 功能失败的解决方法
  9. springMVC引入Validation详解
  10. jQuery之标签操作和返回顶部、登录验证、全选反选、克隆示例
  11. 洛谷P1996 约瑟夫问题【链表】
  12. 命令行下执行python找不包的解决方法
  13. ext 的loadmask 与ajax的同步请求水火不容
  14. 在JAVA中返回类型使用泛型T和Object有什么区别?
  15. scala使用hbase新api
  16. 深入探讨 Java 类加载器(转)
  17. 学习dbms_parallel_execute包
  18. SDK Manager.exe和AVD Manager.exe缺失,Android SDK Tools在检查java环境时卡住了,未响应卡死!
  19. python之定义函数
  20. vue轮播图插件vue-awesome-swiper的使用与组件化

热门文章

  1. Python3解leetcode Factorial Trailing Zeroes
  2. 【2019 Multi-University Training Contest 4】
  3. 10.17 linux 文件权限
  4. (转)docker-compose安装
  5. (转)运行jar应用程序引用其他jar包的四种方法 -- ClassLoader应用
  6. vector代替数组
  7. 建站手册-浏览器信息:Mozilla Firefox 浏览器
  8. Jmeter 线程之间传递参数
  9. MySQL 添加用户、删除用户与授权
  10. oo_project_1