Flutter组件(Widget)之间联动方式整理

这里说的Flutter中Widget之间的联动方式是指一个Widget更新后,另一个Widget得到响应并更新,我们称之为Flutter中Widget之间的联动。下面介绍几种Widget联动的方式。

第一种方式:重新刷新页面

通过setState刷新整个页面,达到更新数据的方式更新对应的控件,代码如下:

/*  
* @Author: yz.yujingzhou     
* @Date: 2020-09-11 22:14:38     
 * @Last Modified by: yz.yujingzhou
 * @Last Modified time: 2020-09-11 22:42:54
**/   

import 'package:flutter/material.dart';

class Way1 extends StatefulWidget {
  @override
  _Way1State createState() => _Way1State();
}

class _Way1State extends State<Way1> {

  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Container(
        alignment: Alignment.center,
        child: Column(
          children: <Widget>[
            GestureDetector(
              onTap: (){
                count--;
                setState(() {
                  
                });
              },
              child: Text('Widget1 Click count-- $count'),
            ),
            Text('I don\'t want to change -- $count'),        
            GestureDetector(
              onTap: (){
                count++;
                setState(() {
                  
                });              
              },
              child: Text('Widget2 Click count++ $count'),
            )                    
          ],
        ),
      ),
    );
  }
}

优点:写法简单明了;
缺点:其实是Widget之间的联动,却需要需要刷新整个页面;

第二种方式:StatefulBuilder / StatefulWidget

这是一种方式的两种实现,StatefulBuilder方式支持在同一个类内直接嵌入Widget实现,而StatefulWidget方式需要把控件另外封装成单独类的方式实现;
适合控件间点对点的控制场景;
先来看看StatefulBuilder的实现方式,代码如下:

/*  
* @Author: yz.yujingzhou     
* @Date: 2020-09-11 22:14:38     
 * @Last Modified by: yz.yujingzhou
 * @Last Modified time: 2020-09-11 22:47:12
**/   

import 'package:flutter/material.dart';

class Way2 extends StatefulWidget {
  @override
  _Way2State createState() => _Way2State();
}

class _Way2State extends State<Way2> {

  int count = 0;
  StateSetter stateSetter1;
  StateSetter stateSetter2;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Container(
        alignment: Alignment.center,
        child: Column(
          children: <Widget>[
            StatefulBuilder(
              builder: (BuildContext context, StateSetter stateSetter){
                stateSetter1 = stateSetter;
                return GestureDetector(
                  onTap: (){
                    count++;
                    stateSetter2(() {
                      
                    });              
                  },
                  child: Text('Widget1 Click count++ $count'),
                );
              }
            ),
            Text('I don\'t want to change -- $count'),      
            StatefulBuilder(
              builder: (BuildContext context, StateSetter stateSetter){
                stateSetter2 = stateSetter;
                return GestureDetector(
                  onTap: (){
                    count++;
                    stateSetter1(() {
                      
                    });              
                  },
                  child: Text('Widget2 Click count++ $count'),
                );
              }
            ),                                 
          ],
        ),
      ),
    );
  }
}

StatefulWidget的实现方式需要封装成两个类,再把各个类的StateSetter通过回调或GlobalKey的方式提供给其它Widget调用达到相互调用的目的,代码很简单就不列举了。
优点:实现联动并点对点局部刷新,适合同一页面位置相互比较接近的Widget之间联动;

第三种方式:ChangeNotifier

这种方式官方控件用得比较多,如TabView,是我比较喜欢用的一种小范围内通知方式,和StatefulWidget类似需要封装,但不需要依赖GlobalKey和回调,很适合页面控件控制某块内容的场景即页对点的控制,同时允许传递值,使用方式如下:

/*  
* @Author: yz.yujingzhou     
* @Date: 2020-09-11 22:14:38     
 * @Last Modified by: yz.yujingzhou
 * @Last Modified time: 2020-09-11 23:11:50
**/   

import 'package:flutter/material.dart';

class Way3 extends StatefulWidget {
  @override
  _Way3State createState() => _Way3State();
}

class _Way3State extends State<Way3> {

  Way3Controller controller;

  @override
  void initState() {
    super.initState();

    controller = Way3Controller(value: 0);
  }
  
  @override
  void dispose() {
    super.dispose();
    controller?.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Container(
        alignment: Alignment.center,
        child: Column(
          children: <Widget>[
            GestureDetector(
              onTap: (){
                controller.value++;
                controller.trigger();             
              },
              child: Text('Widget1 Click'),
            ),
            Text('I don\'t want to change'),      
            Widget2(controller: controller)                                
          ],
        ),
      ),
    );
  }
}

class Widget2 extends StatefulWidget {

  final Way3Controller controller;
  Widget2({this.controller});

  @override
  _Widget2State createState() => _Widget2State();
}

class _Widget2State extends State<Widget2> {

  @override
  void initState() {
    super.initState();

    widget.controller?.addListener((){
      setState(() {
        
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Text('Widget2 Click count++ ${widget.controller?.value}');
  }
}

class Way3Controller extends ChangeNotifier {

  int value;

  Way3Controller({this.value});

  trigger() {
    notifyListeners();
  }
}

第四种方式:InheritedWidget / Provider / Redux

适合较有树形层级的联动场景及信息通信;

第五种方式:EventBus

适合较离散的控件之间的联动场景及信息通信;

Demo代码:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容