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代码:

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值