当前位置: 首页 > news >正文

遵义做企业网站咨询公司组织架构

遵义做企业网站,咨询公司组织架构,微格式wordpress,阿里云的网站空间前言 随着响应式编程的理念Flutter被大众所了解以来#xff0c;状态管理一直是一个引人深思的话题。如果想要学习好Flutter这样的响应式的编程框架就一定是离不开状态管理的。我遇到过很多没有了解过响应式编程框架的#xff0c;或者从事后端开发#xff0c;自己想用F…前言 随着响应式编程的理念Flutter被大众所了解以来状态管理一直是一个引人深思的话题。如果想要学习好Flutter这样的响应式的编程框架就一定是离不开状态管理的。我遇到过很多没有了解过响应式编程框架的或者从事后端开发自己想用Flutter写个app玩玩的朋友一上来不管在哪里都用setState我问为啥不用状态管理大部分都回了一句啥是状态管理当然曾经的我也一样啥也不懂一上来就用上了GetX这个“大杀器”从而导致走了许多弯路。 ps都2023年了已经有那么多的大佬写了与状态管理相关的文章为啥我还要“炒冷饭”因为一句话GetX你害得我好惨同样不同的人对于状态管理有不同的看法一千个读者眼中就会有一千个哈姆雷特。我希望能通过几篇文章来帮助和我类似经历的朋友更好的明白啥是状态管理。 需要我们管理的状态有哪些 在一个应用中存在着大量的状态例如某个组件的动画状态、界面的外观效果、字体…当然很多的状态并不需要我们自己去做管理框架本身就已经做了这部分的工作了例如将Widget树转换为底层的图像或纹理、无需手动跟踪和管理动画状态以及处理布局包括大小、位置和约束无需手动计算和管理布局状态。这才可以让我们开发者更专注于构建用户界面和交互逻辑而无需过多关注底层的状态细节。而需要我们开发者去管理的状态可以分为两类 短时状态 你可以简单的将其理解为某些数据状态只需要在当前的Widget中使用不需要将这些数据和状态共享给其他组件或者页面。通常这样的情况你不需要用到一些provider、GetX这样的状态管理框架你仅仅需要一个StatefulWidget依靠其自身的State管理即可这种状态也不会以复杂的方式而改变。像一个提示消息状态Toast、页面切换时的一些动画淡入淡出效果、动画状态一个淡入淡出的动画或一个旋转动画都是短时状态。 class _MyHomePageState extends StateMyHomePage {Color _buttonColor Colors.blue; // 初始颜色void _changeButtonColor() {setState(() {_buttonColor Colors.green; // 更新颜色为绿色});// 等待1秒后恢复原样Future.delayed(Duration(seconds: 1), () {setState(() {_buttonColor Colors.blue; // 恢复原样});});}overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(短时状态),),body: Center(child: ElevatedButton(onPressed: _changeButtonColor,style: ElevatedButton.styleFrom(backgroundColor: _buttonColor, // 使用当前状态中的颜色padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),),child: const Text(Change Color,style: TextStyle(fontSize: 18),),),),);} }当用户点击 “Change Color” 按钮时按钮的颜色会在一秒钟内变为绿色然后恢复为蓝色。这里的按钮颜色变化过程就是一个短时状态因为它只在特定的时间段内有效不需要长期存储也不需要共享。 应用状态 当数据或状态需要被共享时就是当一个组件的状态发生变化后其他的组件也会跟着发生变化这就是应用状态。建议通过状态管理库如Provider来管理。应用状态的生命周期更长通常会影响应用全局行为例如用户身份、主题、国际化等。 状态提升 在使用状态管理之前我们还需学习下状态提升它能使我们更好的理解到状态管理的作用话不多说直接上案例 可以从图中发现第一个页面的值与第二个页面的值是不同步的。在很多业务场景下都需要将二级的详情页面的值与一级页面的值同步例如文章的点赞数。那么这个时候会有一种简单的方法就是将这个值提取到父级页面由父级页面把状态传递下去。 我们抽离出一个Count类并在父级界面实例化一个Count类通过这种方式第一个页面和第二个页面将共享同一个计数器对象因此无论在哪个页面中增加计数器的值都会同步地影响另一个页面中的计数器。这就实现了状态的提升和同步。不过我们虽然通过状态提升的方法做到了状态同步这一点但是仅仅是一个Count数字的改变却需要将第一个页面和第二个页面上的所有组件进行重新build简单的页面当然看不出什么一旦页面复杂渲染的成本实在是太高也违背了我们使用状态管理的一个初衷控制组件局部刷新。为了能更好的解决这样的问题我们需要探索新的方法这时状态管理就起到作用了 Flutter中有哪些可以做到状态管理 1.setState 我相信无论是新手还是老手只要是体验过Flutter框架99%的朋友都知道setState大部分情况只需要在改变UI数据的逻辑外面套上一个setState就可以实现对界面的更新。在本文中我们不过多讨论setState的使用方式以及原理我们聊聊它的优点和缺点。 优点 相信大家在各种Flutter交流群中应该都有遇到过群友问性能相关的问题。而一些新手朋友这个时候看的多了就会有一个疑惑我写的一些页面也卡卡的帧率只有30几帧会不会是因为我使用了setState去刷新页面啊其实不然setState不但不会造成性能困扰它反而在帮你最关键的一点是因为Flutter在底层实现了一些机制来减少不必要的重绘。 具体一点来说当去调用setState时Flutter会将新的状态放入队列中并计划在下一个绘制周期Frame中更新UI。在下一个绘制周期到来之前Flutter会执行一些优化步骤 差异校验Flutter会比较前后两个状态确定实际上哪些部分需要更新。这种差异校验能够有效地减少不必要的布局、绘制和合成操作。例如合并多个setState调用如果在同一个绘制周期内连续调用了多次setStateFlutter会将它们合并成一个以避免不必要的重复工作。setState只是调用了_element的markNeedsBuild方法以标记这个元素需要在下一个绘制周期中进行重建。这个标记会将新的状态放入队列中并在下一个帧绘制周期中触发重建。重绘策略Flutter会尽量减少需要重新绘制的部分。如果某个部分没有发生变化那么不会重新绘制它从而节省CPU和GPU资源。将组件单独抽离为一个widget就可以通过setState来更新局部状态实现局部刷新。 所以只要能正确的使用setStatesetState的节点越远离根部那么布局、绘制渲染的开销就会越少。使用绝对宽高也可以减少开销哦~ 缺点 聊完了setState的优点那么我们再来聊聊它的缺点 **无法做到跨组件共享数据 **setState是State的函数一般我们会将State的子类设置为私有所以无法做到让别的组件调用State的setState函数来刷新。维护成本极高 在文章的开头就提到过一些新手写Flutter时不管在哪里都用setState搞的哪哪都是。随着页面状态的增多调用setState的地方会越来越多不能统一管理。难以维护。**状态和UI耦合 **使用状态管理很重要的一点就是解耦而随意使用setState会导致数据逻辑和视图混合在一起比如数据库的数据取出来setState到ui上这样编写代码会导致状态和UI耦合在一起不利于测试不利于复用。实现局部刷新复杂度高 setState是整个Widget重新构建子Widget也会跟着销毁重建如果页面足够复杂就会导致非常严重的性能损耗。而如果想要通过setState进行局部刷新就需要对组件进行提取如果每个组件都要封装提取一下这个工作量太多了 2.ChangeNotifier 为了解决setState带来的一些问题可以通过ChangeNotifier作为状态管理的方案。 ChangeNotifier可以将状态逻辑和UI逻辑分开从而使得状态管理更加集中和可控。通过创建一个单独的ChangeNotifier类来管理某一部分状态然后在需要使用这些状态的地方进行订阅。 class CounterModel extends ChangeNotifier {int _counter 0;int get counter _counter;void increment() {_counter;notifyListeners();} }class MyApp extends StatelessWidget {final CounterModel _counterModel CounterModel();overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: Text(ChangeNotifier Example)),body: Column(mainAxisAlignment: MainAxisAlignment.center,children: [CounterDisplay(_counterModel),CounterControl(_counterModel),],),),);} }class CounterDisplay extends StatefulWidget {final CounterModel counterModel;CounterDisplay(this.counterModel);override_CounterDisplayState createState() _CounterDisplayState(); }class _CounterDisplayState extends StateCounterDisplay {overridevoid initState() {super.initState();widget.counterModel.addListener(_update);}overridevoid dispose() {widget.counterModel.removeListener(_update);super.dispose();}void _update() {setState(() {});}overrideWidget build(BuildContext context) {return Center(child: Text(Value: ${widget.counterModel.counter}),);} }class CounterControl extends StatelessWidget {final CounterModel counterModel;const CounterControl(this.counterModel, {Key? key}) : super(key: key);overrideWidget build(BuildContext context) {return Center(child: ElevatedButton(onPressed: () {counterModel.increment();},child: Text(),),);} }不过虽然ChangeNotifier解决了一些问题但在大型应用中仍然可能遇到一些挑战。例如当应用状态较为复杂时可能需要多个ChangeNotifier从而导致状态分散和层级复杂。 3.ChangeNotifierInheritedWidget 在前面我们提到可以通过状态提升的方法实现跨组件之间的数据传递。但是一些简单的小项目都会有很多很多的组件组件之间的继承关系会很复杂如果只是使用状态提升然后通过传参和回调函数这样的方式那么你会发现在继承关系中间的一些组件需要传入大量的参数相当麻烦那怎么让底层的子组件直接去访问被我们提升到父级的状态呢Flutter已经帮我们解决了这个问题就是使用InheritedWidget它可以高效快捷的实现共享数据的跨组件传递。一些初学者可能会觉得InheritedWidget很陌生但是你一定使用过InheritedWidget传递状态的场景 Theme.of(context).primaryColor //获取主题色 MediaQuery.of(context).size.width; // 获取屏幕宽度点击他们的实现源码就可以看到使用了context.dependOnInheritedWidgetOfExactType。使用inheritedWidget的时候会有一个取数据的过程这个时候就会通过子节点的BuildContext使用context.getElementForInheritedWidgetOfExactType 或 context.dependOnInheritedWidgetOfExactType来获取到这个widgetelement从而获取到数据。 InheritedWidget通常用于子组件共享父组件中的数据但它不具备修改更新父组件中数据的能力。它解决了访问状态和根据状态更新的问题但是没有改变状态的能力所以通常会把InheritedWidget和ChangeNotifier结合一起使用通过ChangeNotifier去跟踪变化的数据。 class CounterModel extends ChangeNotifier {int _counter 0;int get counter _counter;void increment() {_counter;notifyListeners(); // Notify listeners when the state changes} }class CounterProvider extends InheritedWidget {final CounterModel counterModel;final Widget child;CounterProvider({required this.counterModel, required this.child}): super(child: child);static CounterProvider? of(BuildContext context) {return context.dependOnInheritedWidgetOfExactTypeCounterProvider();}overridebool updateShouldNotify(CounterProvider oldWidget) {return counterModel ! oldWidget.counterModel;} }class MyApp extends StatelessWidget {final count CounterModel();overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: Text(ChangeNotifier InheritedWidget)),body: CounterProvider(counterModel: count,child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [CounterDisplay(),CounterControl(),],)),),);} }class CounterDisplay extends StatefulWidget {override_CounterDisplayState createState() _CounterDisplayState(); }class _CounterDisplayState extends StateCounterDisplay {late CounterModel counterModel;late VoidCallback listener;overridevoid didChangeDependencies() {super.didChangeDependencies();counterModel CounterProvider.of(context)!.counterModel;listener () {if (mounted) setState(() {});};counterModel.addListener(listener);}overridevoid dispose() {counterModel.removeListener(listener);super.dispose();}overrideWidget build(BuildContext context) {return Center(child: Text(Counter Value: ${counterModel.counter}),);} }class CounterControl extends StatelessWidget {overrideWidget build(BuildContext context) {final counterModel CounterProvider.of(context)!.counterModel;return Center(child: GestureDetector(onTap: () {counterModel.increment();},child: Text(),),);} }通过这样一个简单的例子来体验InheritedWidget结合ChangeNotifier实现状态管理的功能。不过InheritedWidget也存在缺点InheritedWidget的通知机制是基于它的数据发生变化时触发而不是针对特定的子小部件无法定向通知这可能导致不必要的刷新尤其是在大型小部件树中。它会触发整个子小部件树的重建即使只有一部分子小部件受到了影响这也有可能导致性能问题尤其是在需要精细控制刷新的情况下。当然在后续的文章中我们也会详细分析InheritedWidget的实现机制来帮助更好的理解整套流程。同时考虑到这些缺点在后续的文章也会分析更好的状态管理解决方案。 4.Notification Notification是一种用于在小部件树中传递信息的机制它可以用于实现子树中的特定部分之间的通信。Notification并不像状态管理或全局状态传递那样普遍它主要用于特定场景下的通信比如当某个事件发生时需要在小部件树的各个部分之间传递消息。Notification的工作方式是通过Notification对象在小部件树中传递然后从父级小部件开始逐级向上冒泡直到找到一个处理该通知的小部件为止。每个处理通知的小部件可以根据需要执行特定的操作。你可以把InheritedWidget 理解为从上到下传递、共享的方式而Notification则是从下往上。Notification它提供了dispatch方法沿着context对应的Element节点向上逐层发送通知。 class MyNotification extends Notification {final String message;MyNotification(this.message); }class MyApp extends StatelessWidget {overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: Text(Notification)),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [NotificationListenerMyNotification(onNotification: (notification) {print(notification.message);return true;},child: ChildWidget(),),],),),),);} }class ChildWidget extends StatelessWidget {overrideWidget build(BuildContext context) {return ElevatedButton(onPressed: () {MyNotification(Hello 这里是子Widget!).dispatch(context);},child: Text(ChildWidget),);} }当点击按钮后就会向上传递消息被NotificationListener所监听在控制台打印出消息。你可以尝试InheritedWidget Notification来控制状态之间的访问。 5.Stream Stream是一种用于在应用程序中管理状态和数据流的重要工具。Stream是异步数据流的抽象表示它可以在应用程序中传递和监听数据的变化。但是它和Flutter关系并不大它是通过纯dart去实现的。你可以理解为flutter只是通过StreamBuilder去构建了一个Stream通道。它的使用其实也并没有复杂太多通常只需要创建StreamController然后去监听控制器可以直接去监听StreamController然后通过setState更新UI也可以通过StreamBuilder最后将更新后的数据通过Stream的sink属性添加到Stream中即可。知名的状态管理库Bloc就是基于Stream的封装。 class Todo {final String text;bool isCompleted;Todo(this.text, this.isCompleted); }class _TodoAppState extends StateTodoApp {final _controller StreamControllerListTodo();ListTodo _todos [];overridevoid initState() {super.initState();// 初始化Stream将空列表添加到Stream中_controller.sink.add(_todos);}overridevoid dispose() {_controller.close(); // 关闭StreamController以释放资源super.dispose();}void _addTodo(String text) {// 添加新的Todo项并将更新后的列表添加到Stream中final newTodo Todo(text, false);_todos.add(newTodo);_controller.sink.add(_todos);}void _toggleTodoCompletion(int index) {// 切换指定Todo项的完成状态并将更新后的列表添加到Stream中_todos[index].isCompleted !_todos[index].isCompleted;_controller.sink.add(_todos);}void _deleteTodo(int index) {// 删除指定Todo项并将更新后的列表添加到Stream中_todos.removeAt(index);_controller.sink.add(_todos);}overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(备忘录 —— Stream),),body: Column(children: [Padding(padding: EdgeInsets.all(16.0),child: TextField(onSubmitted: (text) {if (text.isNotEmpty) {_addTodo(text);}},decoration: InputDecoration(labelText: 添加任务,border: OutlineInputBorder(),),),),Expanded(child: StreamBuilderListTodo(stream: _controller.stream,builder: (context, snapshot) {if (snapshot.hasData) {return ListView.builder(itemCount: snapshot.data!.length,itemBuilder: (context, index) {final todo snapshot.data![index];return ListTile(title: Text(todo.text),trailing: Checkbox(value: todo.isCompleted,onChanged: (_) _toggleTodoCompletion(index),),onLongPress: () _deleteTodo(index),);},);} else {return Center(child: CircularProgressIndicator());}},),),],),);} }Stream的缺点也同样是它的优点 缺点需要对其定制化才能满足更复杂的场景。优点可以针对业务进行定制化足够灵活可以基于它做一个好的设计。 总结 看完这篇文章后相信您对Flutter中的状态应该有了一个更深刻的记忆。对Flutter自带的状态管理的方式也有了一定的了解那么在后续的文章中我们将进一步深入学习ChangeNotifierInheritedWidget的一些机制以及主流的状态管理框架。在文章的最后我想引用一下flutter.cn的一句话状态管理是一个相当复杂的话题。如果您在浏览后发现一些问题并未得到解答或者并不适用于您的具体需求场景自信些您的实现就是对的。 参考 状态 (State) 管理参考 —— flutter.cn Flutter 工程化框架选择 — 状态管理何去何从 —— 恋猫de小郭 Flutter 对状态管理的认知与思考 —— 小呆呆666 关于我 Hello我是Taxze如果您觉得文章对您有价值希望您能给我的文章点个❤️有问题需要联系我的话我在这里 。如果您觉得文章还差了那么点东西也请通过关注督促我写出更好的文章~万一哪天我进步了呢
http://www.hkea.cn/news/14377171/

相关文章:

  • 济阳做网站开公司怎么做网站
  • 一个完美的网站怎么做电子商务平台的发展趋势
  • 小型网站建设价格低wordpress 检索文件夹
  • 网站开发语言在线检测站长工具seo综合查询adc
  • 如何做网站的百科湛江cms模板建站
  • 网站备案 广东一个网络空间如何做两个网站
  • 网站制作建设飞沐网站建设报价单模板
  • 上饶网站建设多少钱深圳最大的招聘网站是什么
  • 阿坝州网站制作花店如何做推广
  • 苏州市工业园区规划建设局网站丹阳火车站对面规划
  • 萧山建设有限公司网站网站功能报价明细表
  • 设计相关网站汉南做网站
  • 论网站建设情况小程序平台哪个好
  • 现代教育网站开发项目的研究富德生命人寿保险公司官方网站保单查询
  • 电子商务网站建设服务外包梵克雅宝手链
  • 甘肃网站建设推广服务asp手机网站开发教程
  • 深圳设计网站费用大连网站建设方案维护
  • 建设银行的积分网站网站建设比较好
  • 用excel做网站近期热点话题
  • 备案网站域名查询搜索推广平台有哪些
  • 免费好用的网站制作外包网站开发公司
  • 网站建设方案平台架构红酒企业网站模板免费下载
  • 替别人做设计的网站网站如何被搜索到
  • 世界十大网站排名WordPress代码上传头像
  • app公司网站模板做网站必须注册的商标
  • 网站构建的一般流程是什么网页建站网站申请
  • 专业做旅游网站建工集团领导班子名单
  • 百度上推广一个网站该怎么做广州东圃网站建设公司
  • 在线网站建设收费电子商务网站建设项目的阶段
  • 网站开发系统学习网站备案是一年一次吗