Flutter 入门与实战(七十五):模拟红绿灯来看GetX的定向刷新

您所在的位置:网站首页 倒计时数字红绿灯怎么看 Flutter 入门与实战(七十五):模拟红绿灯来看GetX的定向刷新

Flutter 入门与实战(七十五):模拟红绿灯来看GetX的定向刷新

2023-04-23 18:26| 来源: 网络整理| 查看: 265

前言

对于有些场景,我们可能有多个组件共享一份状态数据,但是状态数据改变后可能只需要更新其中的一个或多个组件,而不是依赖状态的全部组件。这个时候我们就可以用到 GetX 的定向更新。GetX 在 update 方法中可以提供两个可选参数:

void update([List? ids, bool condition = true]) { if (!condition) { return; } if (ids == null) { refresh(); } else { for (final id in ids) { refreshGroup(id); } } } 复制代码 ids:要更新的 id数组,id可以在 GetBuilder 构建的时候指定,若指定了ids,则之后更新与 ids 中的 id 匹配的组件: GetBuilder( id: 'text' init: Controller(), // use it only first time on each controller builder: (_) => Text( '${Get.find().counter}', //here ), ), 复制代码 condition:条件表达式,只有当这个条件为真的时候才会更新组件。

例如下面的代码只会在 counter 小于10的时候更新 id 为 text 的组件。

update(['text'], counter < 10); 复制代码

接下来我们模拟带倒计时的红绿灯来演示GetX 的定向更新的使用。

业务逻辑

为了分别控制红绿灯,我们需要三个组件,分别是红灯、绿灯和黄灯。

image.png

然后是倒计时,我们设置规则如下:

绿灯亮的时长为20秒,红灯为10秒,黄灯为3秒,计时通过定时器完成,每隔1秒减1。 三个红灯共用一个计时器,但根据当前亮的灯的状态来定向更新哪个灯的倒计时时间,同时对于不亮的灯我们不显示倒计时时间(因为共享了倒计时时间,如果显示就会不对)。 使用一个枚举来确定当前亮哪个灯,亮灯的次序为绿灯->黄灯->红灯->绿灯……

业务理顺了,开始撸代码!

红绿灯代码

首先我们构建一个通用的交通灯的组件 TrafficLed,需要四个参数:

灯的颜色:ledColor,控制灯的倒计时数字颜色; 倒计时时间:secondsLeft,倒计时时间; 是否显示倒计时:showSeconds,使用 Offstate 控制是否显示倒计时时间。 灯的大小:ledSize,默认尺寸为60,用于控制灯的尺寸。

对应代码很简单,这里我们为了好看做了点阴影,使得看起来有点立体感。

class TrafficLed extends StatelessWidget { final Color ledColor; final int secondsLeft; final bool showSeconds; final double ledSize; const TrafficLed({ Key? key, required this.ledColor, required this.secondsLeft, required this.showSeconds, this.ledSize = 60.0, }) : super(key: key); @override Widget build(BuildContext context) { return Center( child: Container( alignment: Alignment.center, width: ledSize, height: ledSize, decoration: BoxDecoration( color: Colors.black, borderRadius: BorderRadius.circular(ledSize / 2), boxShadow: [ BoxShadow( color: Color(0xFF505050), offset: Offset(1, -1), blurRadius: 0.2, ) ], ), child: Offstage( child: Text( '$secondsLeft', textAlign: TextAlign.center, style: TextStyle( color: this.ledColor, fontSize: 36, fontWeight: FontWeight.bold, ), ), offstage: !showSeconds, ), ), ); } } 复制代码

接下来是整个灯的组合,这里我们使用横向的红绿灯,然后也用阴影做了一个有立体感的背景。关键代码在每个灯都使用了 GetBuilder 包裹,然后指定了每个灯的 id,这里以绿灯为例:

GetBuilder( id: 'green', init: lightController, builder: (state) => TrafficLed( ledColor: (state.currentLight == TrafficLight.green ? Colors.green : Colors.black), secondsLeft: state.counter, showSeconds: state.currentLight == TrafficLight.green, ), ), 复制代码

每个灯对应的逻辑如下:

如果当前状态中显示的灯和自身一致,倒计时的文字颜色就使用灯对应的颜色,即红、黄、绿;否则显示黑色(和背景色一致); 绑定状态对象的倒计时时间; 如果当前状态中显示的灯和自身一致,则显示倒计时,否则不显示。 状态管理代码

状态管理控制器为TrafficLightController,代码如下:

enum TrafficLight { green, red, yellow } class TrafficLightController extends GetxController { late TrafficLight _currentLight; get currentLight => _currentLight; int _counter = 0; get counter => _counter; late Timer _downcountTimer; @override void onInit() { _counter = 20; _currentLight = TrafficLight.green; super.onInit(); } @override void onReady() { _downcountTimer = Timer.periodic(Duration(seconds: 1), decreament); super.onReady(); } void decreament(Timer timer) { _counter--; if (_counter == 0) { switch (_currentLight) { case TrafficLight.green: _currentLight = TrafficLight.yellow; _counter = 3; update(['green', 'yellow']); break; case TrafficLight.yellow: _currentLight = TrafficLight.red; _counter = 10; update(['red', 'yellow']); break; case TrafficLight.red: _currentLight = TrafficLight.green; _counter = 20; update(['red', 'green']); break; } } else { switch (_currentLight) { case TrafficLight.green: update(['green']); break; case TrafficLight.yellow: update(['yellow']); break; case TrafficLight.red: update(['red']); break; } } } @override void onClose() { _downcountTimer.cancel(); super.onClose(); } } 复制代码

这里使用了三个声明周期函数:

onInit:设置倒计时时间为20秒,灯状态为绿灯; onReady:启动定时器; onClose:关闭定时器。

核心业务逻辑都在 decreament 这个定时器回调方法里,这里如果倒计时到0的时候我们切换灯状态,重置倒计时时间,而且只更新该情况下需要刷新的灯(每次2个灯需要更新)。如果倒计时没有到0,那么我们只需要更新当前亮的灯就可以了。通过这种方式,我们可以定向更新,在共享状态数据的同时还可以减少不必要的刷新。

运行效果

运行效果如下图,源码已提交至:GetX 相关代码。

屏幕录制2021-09-07 下午10.13.18.gif

总结

本篇介绍了 GetX 的 GetBuilder使用id参数实现定向刷新的特性。这种情况适用于多个组件共用一个状态对象,但更新条件不同的情况,比如本例的红绿灯。同时,GetxController 的 update 方法还可以实现条件更新,通过id 加条件组合能够实现更加精准的定向刷新。

我是岛上码农,微信公众号同名,这是Flutter 入门与实战的专栏文章,提供体系化的 Flutter 学习文章。对应源码请看这里:Flutter 入门与实战专栏源码。如有问题可以加本人微信交流,微信号:island-coder。

👍🏻:觉得有收获请点个赞鼓励一下!

🌟:收藏文章,方便回看哦!

💬:评论交流,互相进步!



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3