一,概述 

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

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

二, 通信实现方式

  • 回调通信

    • 需求“点击子组件,修改父组件的背景颜色与子组件背景颜色一致”
    • 代码实现
      1. //父组件
      2.  
      3. class ParentWidget extends StatefulWidget {
      4. final String title;
      5. ParentWidget({Key key,this.title}):super(key:key);
      6.  
      7. @override
      8. State<StatefulWidget> createState() {
      9. return new ParentWidgetState();
      10. }
      11. }
      12.  
      13. class ParentWidgetState extends State<ParentWidget> {
      14. Color containerBg = Colors.orange;
        //回调函数
      15. void changeBackgroundColor(Color newColor){
      16. setState(() {
      17. containerBg = newColor;//修改状态
      18. });
      19. }
      20.  
      21. @override
      22. Widget build(BuildContext context) {
      23. return new Scaffold(
      24. appBar: new AppBar(
      25. title: new Text(widget.title),
      26. ),
      27. body: new Center(
      28. child: new GestureDetector(
      29. onTap: (){
      30. changeBackgroundColor(Colors.orange);
      31. },
      32. child: new Container(
      33. width: 300,
      34. height: 300,
      35. color: containerBg,
      36. alignment: Alignment.center,
      37. child: new Row(
      38. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      39. children: <Widget>[
      40. new childrenA(childrenACallBack: changeBackgroundColor),
      41. new childrenB(childrenBCallBack: changeBackgroundColor),
      42. ],
      43. ),
      44. ),
      45. )
      46. ),
      47. );
      48. }
      49. }
      50.  
      51. //子组件(组件A)
      52. class childrenA extends StatelessWidget {
        //定义接收父类回调函数的指针
      1. final ValueChanged<Color> childrenACallBack;
      2. childrenA({Key key,this.childrenACallBack}):super(key:key);
      1. @override
      2. Widget build(BuildContext context) {
      3. return new GestureDetector(
      4. onTap: (){
           //调用回调函数传值
      5. childrenACallBack(Colors.green);
      6. },
      7. child: new Container(
      8. width: 80,
      9. height: 80,
      10. color: Colors.green,
      11. child: new Text('ChildrenA'),
      12. ),
      13. );
      14. }
      15. }
      16.  
      17. //子组件(组件B)
      18. class childrenB extends StatelessWidget {
      19. final ValueChanged<Color> childrenBCallBack;
      20. childrenB({Key key,this.childrenBCallBack}):super(key:key);
      21.  
      22. @override
      23. Widget build(BuildContext context) {
      24. return new GestureDetector(
      25. onTap:(){
      26. childrenBCallBack(Colors.red);
      27. },
      28. child: new Container(
      29. width: 80,
      30. height: 80,
      31. color: Colors.red,
      32. child: new Text('ChildredB'),
      33. ),
      34. );
      35. }
      36. }
    • 功能实现

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

    • 场景:业务开发中经常会碰到这样的情况,多个Widget需要同步同一份全局数据,比如点赞数、评论数、夜间模式等等。
    • 代码实现:
      1. import 'package:flutter/material.dart';
      2.  
      3. void main() => runApp(MyApp());
      4.  
      5. class MyApp extends StatelessWidget {
      6. // This widget is the root of your application.
      7. @override
      8. Widget build(BuildContext context) {
      9. return MaterialApp(
      10. title: 'Flutter Demo',
      11. theme: ThemeData(
      12. primarySwatch: Colors.blue,
      13.  
      14. ),
      15. home: new InheritedWidgetTestContainer(),
      16. );
      17. }
      18. }
      19.  
      20. //模型数据
      21. class InheritedTestModel {
      22. final int count;
      23. const InheritedTestModel(this.count);
      24. }
      25.  
      26. //哨所(自定义InheritedWidget类)
      27. class InheritedContext extends InheritedWidget {
      28. //构造函数
      29. InheritedContext({
      30. Key key,
      31. @required this.inheritedTestModel,
      32. @required this.increment,
      33. @required this.reduce,
      34. @required Widget child
      35. }):super(key:key,child:child);
      36.  
      37. //变量
      38. final InheritedTestModel inheritedTestModel;
      39. final Function() increment;
      40. final Function() reduce;
      41.  
      42. //静态方法
      43. static InheritedContext of(BuildContext context){
      44. InheritedContext contexts = context.inheritFromWidgetOfExactType(InheritedContext);
      45. return context.inheritFromWidgetOfExactType(InheritedContext);
      46. }
      47. //是否重建取决于Widget组件是否相同
      48. @override
      49. bool updateShouldNotify(InheritedContext oldWidget) {
      50. return inheritedTestModel != oldWidget.inheritedTestModel;
      51. }
      52. }
      53.  
      54. class TestWidgetA extends StatelessWidget {
      55. @override
      56. Widget build(BuildContext context) {
      57. final inheritedContext = InheritedContext.of(context);
      58. return new Padding(
      59. padding: const EdgeInsets.only(left: 10.0,top: 10.0,right: 10.0),
      60. child: new RaisedButton(
      61. textColor: Colors.black,
      62. child: new Text('+'),
      63. onPressed:inheritedContext.increment
      64. ),
      65. );
      66. }
      67. }
      68.  
      69. class TestWidgetB extends StatelessWidget {
      70. @override
      71. Widget build(BuildContext context) {
      72. final inheritedContext = InheritedContext.of(context);
      73. return new Padding(
      74. padding: const EdgeInsets.only(left: 10,top: 10,right: 10.0),
      75. child: new RaisedButton(
      76. textColor: Colors.black,
      77. child: new Text('-'),
      78. onPressed: inheritedContext.reduce
      79. ),
      80. );
      81. }
      82. }
      83.  
      84. class TestWidgetC extends StatelessWidget {
      85. @override
      86. Widget build(BuildContext context) {
      87. final inheritedContext = InheritedContext.of(context);
      88. final inheritedTestModel = inheritedContext.inheritedTestModel;
      89.  
      90. return new Padding(
      91. padding: const EdgeInsets.only(left: 10.0,top: 10.0,right: 10.0),
      92. child: new RaisedButton(
      93. textColor: Colors.black,
      94. child: new Text('${inheritedTestModel.count}'),
      95. onPressed: (){
      96.  
      97. },
      98. ),
      99. );
      100. }
      101. }
      102.  
      103. class InheritedWidgetTestContainer extends StatefulWidget {
      104. @override
      105. State<StatefulWidget> createState() {
      106. return new InheritedWidgetTestContainerState();
      107. }
      108. }
      109.  
      110. class InheritedWidgetTestContainerState extends State<InheritedWidgetTestContainer> {
      111.  
      112. InheritedTestModel _inheritedTestModel;
      113.  
      114. _initData(){
      115. _inheritedTestModel = new InheritedTestModel(0);
      116. }
      117.  
      118. @override
      119. void initState() {
      120. _initData();
      121. super.initState();
      122. }
      123.  
      124. _incrementCount(){
      125. setState(() {
      126. _inheritedTestModel = new InheritedTestModel(_inheritedTestModel.count + 1);
      127. });
      128. }
      129.  
      130. _reduceCount(){
      131. setState(() {
      132. _inheritedTestModel = new InheritedTestModel(_inheritedTestModel.count - 1);
      133. });
      134. }
      135.  
      136. @override
      137. Widget build(BuildContext context) {
      138. return new InheritedContext(
      139. inheritedTestModel: _inheritedTestModel,
      140. increment: _incrementCount,
      141. reduce: _reduceCount,
      142. child: new Scaffold(
      143. appBar: new AppBar(
      144. title: new Text('InheritedWidgetTest'),
      145. ),
      146. body: new Center(
      147. child: new Column(
      148. children: <Widget>[
      149. new TestWidgetA(),
      150. new TestWidgetB(),
      151. new TestWidgetC(),
      152. ],
      153. ),
      154. )
      155. ),
      156. );
      157. }
      158. }
    • 功能实现
       
    • 使用场景
      一般用于父组件对子组件的跨组件传值。

  • Global Key通信
    GlobalKey能够跨Widget访问状态。
    • 需求“点击A子组件,修改B子组件的背景颜色为指定的‘蓝色”
    • 代码实现
      1. //父组件
      2. class ParentWidget extends StatefulWidget {
      3. @override
      4. State<StatefulWidget> createState() {
      5. return new ParentWidgetState();
      6. }
      7. }
      8.  
      9. class ParentWidgetState extends State<ParentWidget> {
      10. @override
      11. Widget build(BuildContext context) {
      12.  
      13. return new Scaffold(
      14. appBar: new AppBar(
      15. title: new Text('组件化'),
      16. ),
      17. body: new Center(
      18. child: new Container(
      19. color: Colors.grey,
      20. width: 200,
      21. height: 200,
      22. child: new Row(
      23. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      24. children: <Widget>[
      25. new SubWidgetA(key: subAkey),
      26. new SubWidgetB(key: subBkey)
      27. ],
      28. ),
      29. ),
      30. ),
      31. );
      32. }
      33. }
      34.  
      35. //子组件A
      36.  
      37. class SubWidgetA extends StatefulWidget {
      38. SubWidgetA({Key key}):super(key:key);
      39. @override
      40. State<StatefulWidget> createState() {
      41. return new SubWidgetAState();
      42. }
      43. }
      44.  
      45. class SubWidgetAState extends State <SubWidgetA> {
      46.  
      47. Color _backgroundColors = Colors.red;//红色
      48. void updateBackGroundColors(Color colos){
      49. setState(() {
      50. _backgroundColors = colos;
      51. });
      52. }
      53.  
      54. @override
      55. Widget build(BuildContext context) {
      56. return new GestureDetector(
      57. onTap: (){
      58. subBkey.currentState.updateBackGroundColors(Colors.blue);
      59. setState(() {
      60. _backgroundColors = Colors.red;
      61. });
      62. },
      63. child: new Container(
      64. width: 80,
      65. height: 80,
      66. color:_backgroundColors,
      67. alignment: Alignment.center,
      68. child: new Text('SubWidgetA'),
      69. ),
      70. );
      71. }
      72. }
      73.  
      74. //子组件B
      75. class SubWidgetB extends StatefulWidget {
      76. SubWidgetB({Key key}):super(key:key);
      77. @override
      78. State<StatefulWidget> createState() {
      79. // TODO: implement createState
      80. return new SubWidgetBState();
      81. }
      82. }
      83.  
      84. class SubWidgetBState extends State<SubWidgetB> {
      85.  
      86. Color _backgroundColors = Colors.green;//绿色
      87. void updateBackGroundColors(Color colos){
      88. setState(() {
      89. _backgroundColors = colos;
      90. });
      91. }
      92.  
      93. @override
      94. Widget build(BuildContext context) {
      95. return new GestureDetector(
      96. onTap: (){
      97. subAkey.currentState.updateBackGroundColors(Colors.blue);
      98. setState(() {
      99. _backgroundColors = Colors.green;
      100. });
      101.  
      102. },
      103. child: new Container(
      104. width: 80,
      105. height: 80,
      106. color: _backgroundColors,
      107. alignment: Alignment.center,
      108. child: new Text('SubWidgetB'),
      109. ),
      110. );
      111. }
      112. }
    • 功能实现
    • 使用场景:一般用于跨组件访问状态
  • ValueNotifier通信 

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

    1. 定义ValueNotifierData类,继承ValueNotifier

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

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

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

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

      • 引入插件

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

        • 新建消息监测类

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

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

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

【Flutter学习】组件通信(父子、兄弟)的更多相关文章

  1. react第六单元(react组件通信-父子组件通信-子父组件通信-跨级组件的传参方式-context方式的传参)

    第六单元(react组件通信-父子组件通信-子父组件通信-跨级组件的传参方式-context方式的传参) #课程目标 1.梳理react组件之间的关系 2.掌握父子传值的方法 3.掌握子父传值的方法 ...

  2. vue组件之间的通信, 父子组件通信,兄弟组件通信

    组件通讯包括:父子组件间的通信和兄弟组件间的通信.在组件化系统构建中,组件间通信必不可少的. 父组件--> 子组件 1. 属性设置 父组件关键代码如下: <template> < ...

  3. vue组件通信&&v兄弟组件通信eventbus遇到的问题(多次触发、第一次不触发)

    组件通讯包括:父子组件间的通信和兄弟组件间的通信.在组件化系统构建中,组件间通信必不可少的 (vuex以后再说). 父组件--> 子组件 1. 属性设置 父组件关键代码如下: <templ ...

  4. 计算属性、侦听属性、局部与全局组件使用、组件通信(父子互传)、ref属性、动态组件和keep-alive、插槽

    今日内容概要 计算属性 侦听属性 局部组件和全局组件 组件通信之父传子 组件通信之子传父 ref属性(组件间通信) 动态组件和keep-alive 插槽 内容详细 1.计算属性 # 插值的普通函数,只 ...

  5. vue组件详解——组件通信

    每天学习一点点 编程PDF电子书.视频教程免费下载:http://www.shitanlife.com/code 组件之间通信可以用下图表示: 组件关系可分为父子组件通信.兄弟组件通信.跨级组件通信. ...

  6. vue组件详解(三)——组件通信

    组件之间通信可以用下图表示: 组件关系可分为父子组件通信.兄弟组件通信.跨级组件通信. 一.自定义事件 当子组件需要向父组件传递数据时,就要用到自定义事件. 子组件用$emit ()来触发事件,父组件 ...

  7. vue2.0 $emit $on组件通信

    在vue1.0中父子组件通信使用$dispatch 和 $broadcast,但是在vue2.0中$dispatch 和 $broadcast 已经被弃用. 因为基于组件树结构的事件流方式实在是让人难 ...

  8. vue 2 使用Bus.js进行兄弟(非父子)组件通信 简单案例

    vue2中废弃了$dispatch和$broadcast广播和分发事件的方法.父子组件中可以用props和$emit().如何实现非父子组件间的通信,可以通过实例一个vue实例Bus作为媒介,要相互通 ...

  9. vue2.0 父子组件通信 兄弟组件通信

    父组件是通过props属性给子组件通信的来看下代码: 父组件: <parent> <child :child-com="content"></chil ...

随机推荐

  1. MaxCompute studio FAQ

    1. 官方文档地址 https://help.aliyun.com/document_detail/50889.html 2. Show Table Detail 中文乱码 原因是Intellij A ...

  2. 使用C#获取IP地址方法

    C#中如何获取IP地址?,看到问题的时候我也很纠结,纠结的不是这个问题是如何的难回答,而是纠结的是这些问题都是比较基本的常识,也是大家会经常用到的.但是却不断的有人问起,追根究底的原因估计就是没有好好 ...

  3. 七、单例设计模式共享数据分析、解决、call_once

    一.设计模式大概谈 代码的一些写法,与常规的写法不太一样,程序灵活,维护起来很方便,但是别人接管.阅读代码很痛苦. 用设计模式理念写出来的代码很晦涩.<< head first>&g ...

  4. puppet(一种Linux、Unix、windows平台的集中配置管理系统)

    puppet是一种Linux.Unix.windows平台的集中配置管理系统,使用自有的puppet描述语言,可管理配置文件.用户.cron任务.软件包.系统服务等.puppet把这些系统实体称之为资 ...

  5. 20 October in ss

    Contest A: sum 快速读. B: 鬼谷子的钱袋(coin) 贪心. 按照类似二进制的方式准备钱袋:1, 2, 4, 8, ... 以此装入的钱袋数目记为 \(N\). 如果最后剩余不足以凑 ...

  6. Linux环境下对大小写敏感,linux环境升级node

    linux对大小写敏感 在window下可以正常运行的代码,在linux环境下报错,找不到文件,因为window下对大小写不敏感,linux对大小写敏感 linux环境下node升级 1.安装nvm ...

  7. upc组队赛15 Made In Heaven【第K短路 A*】

    Made In Heaven 题目描述 One day in the jail, F·F invites Jolyne Kujo (JOJO in brief) to play tennis with ...

  8. Java并发AtomicReference类

    java.util.concurrent.atomic.AtomicReference类提供了可以原子读取和写入的底层对象引用的操作,还包含高级原子操作. AtomicReference支持对底层对象 ...

  9. (4.10)sql server导入导出

    SQL Server快速导入数据分享 核心参考:官网~~https://docs.microsoft.com/zh-cn/sql/relational-databases/import-export/ ...

  10. webstorm的下载、破解、与汉化

    其实很简单的事情,都被我弄复杂了倒腾了很久,特做个记录. 说明前提,版本为 webstorm 2018.1.4 一.下载webstorom 下载地址:当然去官网啊  https://www.jetbr ...