很多朋友在找时都会咨询flutter状态管理和flutter状态管理方案,这说明有一部分人对这个问题不太了解,您了解吗?那么什么是flutter状态管理方案?下面就由小编带大家详细了解一下吧!
这里的DynamicHabitDetailViewModel实例对象由ChangeNotifierProxyProvider提供,ChangeNotifierProxyProvider组合了两种功能:
(1)它会自动订阅DynamicHabitDetailViewModel中的更改(如果您只想使用此功能,只需使用ChangeNotifierProvider)
(2)它采用先前提供的对象的值(在本例中为TeamDetailViewModel,如上所述),并使用它来构建DynamicHabitDetailViewModel的值(如果您只需要此功能,只需使用ProxyProvider,也就是项目中的ChangeNotifierProxyProvider)
一、前言
Flutter开发,就需要对各种状态的管理,就是在请求数据的时候需要实时变化,各种交互变化等,在没有使用GetX之前使用Provider,用Provider的时候觉得真香,挺方便的,需要刷新的时候直接 notifyListeners(); 用了GetX之后觉得Provider太繁琐了。这边介绍下GetX的使用以及常用的方法。
二、 GetX
GetX 是 Flutter 上的一个轻量且强大的解决方案:高性能的状态管理、智能的依赖注入和便捷的路由管理。
1、相关优势:
三、使用
1、第一步 引入get
2、第二步
修改入口、配置路由
3、路由
Routes类
Pages类
4、状态管理
我一般一个page对应一个controller, controller来处理逻辑,控制page.
简单使用
5、依赖注入
依赖注入也是我喜欢的,可以减少很多工作。
第一步
第二步
6、跨页面交互
7、黑暗模式
可以参考前期写的博客。 黑暗模式的适配
使用这个版本的GetX写了Demo之后,发现有几个问题:
感觉不太像是稳定版本,存在一些比较明显的问题;而且2.0.6到2.0.7只是一个小版本,全局状态管理逻辑似乎就有比较大的改动。
不支持响应式编程,这个版本的状态管理还是基于state的逻辑;因为想要比较高效的解耦页面和逻辑,可能需要搭配响应式编程框架。
相关功能可能比较少,没有最新版本的功能那么全面。
Flutter是Google开源的构建用户界面(UI)工具包,帮助开发者通过一套代码库高效构建多平台精美应用,支持移动、Web、桌面和嵌入式平台。
Flutter 开源、免费,拥有宽松的开源协议,适合商业项目。Flutter已推出稳定的2.0版本。
产生背景:
Flutter可以方便的加入现有的工程中。在全世界,Flutter 正在被越来越多的开发者和组织使用,并且 Flutter是完全免费、开源的。它也是构建未来的 Google Fuchsia 应用的主要方式。
Flutter组件采用现代响应式框架构建,这是从React中获得的灵感,中心思想是用组件(widget)构建你的UI。
组件描述了在给定其当前配置和状态时他们显示的样子。当组件状态改变,组件会重构它的描述(description),Flutter 会对比之前的描述, 以确定底层渲染树从当前状态转换到下一个状态所需要的最小更改。
ScopedModel可以全局+局部使用(即使用了全局ScopedModel,也不影响某个Widget使用自己的ScopedModel)
最近公司做技术分享写的文章的demo
Flutter中的InheritedWidget状态管理
1.InheritedWidget是什么?
InheritedWidget是Flutter中非常重要的一个功能型组件,它提供了一种数据在widget树中从上到下传递、共享的方式,比如我们在应用的根widget中通过InheritedWidget共享了一个数据,那么我们便可以在任意子widget中来获取该共享的数据!这个特性在一些需要在widget树中共享数据的场景中非常方便!如Flutter SDK中正是通过InheritedWidget来共享应用主题(Theme)和Locale (当前语言环境)信息的。
InheritedWidget和React中的context功能类似,和逐级传递数据相比,它们能实现组件跨级传递数据。InheritedWidget的在widget树中数据传递方向是从上到下的,这和通知Notification的传递方向正好相反。
2.源码分析
InheritedWidget
先来看下InheritedWidget的源码:
abstract class?InheritedWidget?extends?ProxyWidget { ??const?InheritedWidget({ Key key,?Widget child }):?super(key: key,?child: child);??@override??InheritedElement?createElement() =InheritedElement(this);??@protected??bool?updateShouldNotify(covariant?InheritedWidget oldWidget);}
它继承自ProxyWidget:
abstract class?ProxyWidget?extends?Widget { ??const?ProxyWidget({ Key key,?@required?this.child?}) :?super(key: key);??final?Widget?child;}
可以看出Widget内除了实现了createElement方法外没有其他操作了,它的实现关键一定就是InheritedElement了。
InheritedElement 来看下InheritedElement源码
class?InheritedElement?extends?ProxyElement { ??InheritedElement(InheritedWidget widget) :?super(widget);??@override??InheritedWidget?get?widget?=?super.widget;??// 这个Set记录了所有依赖的Elementfinal?MapElement,?Object?_dependents?=?HashMapElement,?Object();
//该方法会在Element mount和activate方法中调用,_inheritedWidgets为基类Element中的成员,用于提高Widget查找父节点中的InheritedWidget的效率,它使用HashMap缓存了该节点的父节点中所有相关的InheritedElement,因此查找的时间复杂度为o(1) ??@override??void?_updateInheritance() {final?MapType,?InheritedElement incomingWidgets =?_parent?._inheritedWidgets;if?(incomingWidgets !=?null)??????_inheritedWidgets?=?HashMapType,?InheritedElement.from(incomingWidgets);????else??????_inheritedWidgets?=?HashMapType,?InheritedElement();????_inheritedWidgets[widget.runtimeType] =?this;??}
//该方法在父类ProxyElement中调用,看名字就知道是通知依赖方该进行更新了,这里首先会调用重写的updateShouldNotify方法是否需要进行更新,然后遍历_dependents列表并调用didChangeDependencies方法,该方法内会调用mardNeedsBuild,于是在下一帧绘制流程中,对应的Widget就会进行rebuild,界面也就进行了更新 ??@override??void?notifyClients(InheritedWidget oldWidget) {????assert(_debugCheckOwnerBuildTargetExists(‘notifyClients’));for?(Element dependent?in?_dependents.keys) {??????notifyDependent(oldWidget,?dependent);????}??}
其中_updateInheritance方法在基类Element中的实现如下:
void _updateInheritance() {
??_inheritedWidgets = _parent?._inheritedWidgets;
}
总结来说就是Element在mount的过程中,如果不是InheritedElement,就简单的将缓存指向父节点的缓存,如果是InheritedElement,就创建一个缓存的副本,然后将自身添加到该副本中,这样做会有两个值得注意的点:
InheritedElement的父节点们是无法查找到自己的,即InheritedWidget的数据只能由父节点向子节点传递,反之不能。
如果某节点的父节点有不止一个同一类型的InheritedWidget,调用inheritFromWidgetOfExactType获取到的是离自身最近的该类型的InheritedWidget。
看到这里似乎还有一个问题没有解决,依赖它的Widget是在何时被添加到_dependents这个列表中的呢?
回忆一下从InheritedWidget中取数据的过程,对于InheritedWidget有一个通用的约定就是添加static的of方法,该方法中通过inheritFromWidgetOfExactType找到parent中对应类型的的InheritedWidget的实例并返回,与此同时,也将自己注册到了依赖列表中,该方法的实现位于Element类,实现如下:
@overrideT?dependOnInheritedWidgetOfExactType
// 这里通过上述mount过程中建立的HashMap缓存找到对应类型的InheritedElement final?InheritedElement ancestor =?_inheritedWidgets?==?null???null?:?_inheritedWidgets[T];if?(ancestor !=?null) {????assert(ancestor?is?InheritedElement);return?dependOnInheritedElement(ancestor,?aspect: aspect);??}??_hadUnsatisfiedDependencies?=?true;??return null;}
@overrideInheritedWidget?dependOnInheritedElement(InheritedElement ancestor,?{ Object aspect }) {??assert(ancestor !=?null);
// 这个列表记录了当前Element依赖的所有InheritedElement,用于在当前Element deactivate时,将自己从InheritedElement的_dependents列表中移除,避免不必要的更新操作 ??_dependencies???=?HashSetInheritedElement();??_dependencies.add(ancestor);??ancestor.updateDependencies(this,?aspect);return?ancestor.widget;}
3.如何使用InheritedWidget
1)、创建一个类继承自Inheritedwidget
class?InheritedContext?extends?InheritedWidget{??final?InheritedTestModel?inheritedTestModel;??InheritedContext({????Key key,????@required?this.inheritedTestModel,????@required?Widget child}):?super(key: key,?child: child);static?InheritedContext? of (BuildContext context) {????return?context.dependOnInheritedWidgetOfExactTypeInheritedContext();??}??@override??bool?updateShouldNotify(InheritedContext oldWidget) {????return?inheritedTestModel?!= oldWidget.inheritedTestModel;??}}
2)、InheritedTestModel类为数据容器(这里定义了一个Listint数据源)
class?InheritedTestModel{?final?List?_list;??InheritedTestModel(this._list);??List?getList(){????return?_list;??}}
class?ArrayListData{??static?List? _list ;static?List? getListData (){???? _list? =?new?List();???? _list .add(1);???? _list .add(2);???? _list .add(3);???? _list .add(4);return? _list ;??}}
3)、定义一个Widget?使用?InheritedContext类的数据?InheritedTestModel?
class?ListDemo?extends?StatefulWidget{??@override??State?createState() {????return new?ListDemoState();??}}class?ListDemoState?extends?StateListDemo{List?_list;??InheritedTestModel?_inheritedTestModel;??Timer?_timer;??Duration?oneSec?=?const?Duration(seconds:?1);??@override??void?initState() {????_list?= ArrayListData. getListData ();????_inheritedTestModel?=?new?InheritedTestModel(_list);????_timer?=?Timer.periodic(oneSec,?(timer) {??????_doTimer();????});??}??void?_doTimer() {????for(int i =?0;?i ?_list.length;?i++){??????_list[i] =?_list[i]+?1;????}??setState(() {????_inheritedTestModel?=?new?InheritedTestModel(_list);??});??}Widget?_buildBody() {????return?Container(child:?ListDemo2(),????);??}??@override??Widget?build(BuildContext context) {????return?InheritedContext(inheritedTestModel:?_inheritedTestModel,??????child:?Scaffold(appBar:?AppBar(title:?Text(“ListDemo”),????????actions: Widget[????????????IconButton(icon:?Icon(Icons. add ),????????????)????????],),????????body: _buildBody(),??????),????);??}??@override??void?dispose() {????super.dispose();if?(_timer?!=?null) {??????_timer.cancel();????}??}}
4)、在ListDemo中通过Timer更新InheritedTestModel?中的数据,然后再下一个Widget中获取更新的数据作为展示
class?ListDemo2?extends?StatefulWidget{??@override??State?createState() {????return new?ListDemoState2();??}}class?ListDemoState2?extends?StateListDemo2{InheritedTestModel?_inheritedTestModel;??Widget?_buildListItem(BuildContext context,int index) {????return ?Container(height:?50,????????width:?100,????????alignment: Alignment. center ,????????child:?Text(_inheritedTestModel.getList()[index].toString()),????);??}Widget?_buildBody() {????_inheritedTestModel?= InheritedContext. of (context).inheritedTestModel;return?Container(child:?ListView.builder(itemBuilder:(context,?index)=_buildListItem(context,index),itemCount:?_inheritedTestModel.getList().length,),????);??}??@override??Widget?build(BuildContext context) {????return ?_buildBody();??}}
这样就可以在父widget中更新数据,子View不需任何操作直接从数据容器InheritedTestModel?中获取到更新后的新数据
这是一个数据共享的简单的例子,基本的流程,大致就是A去更新B的数据,A和B有一个共同的父类,实现数据的共享
4.上面说了原理和基本的使用,但是在实际项目当中,我当然不建议这样来使用,Google?已经为我们封装好了功能更加强大的插件Provider,其内部原理就是基于InheritedWidget来实现的,我们理解了基本原理,可以更好的在项目中运用Provider
flutter状态管理的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于flutter状态管理方案、flutter状态管理的信息别忘了在本站进行查找喔。