flutter状态管理[flutter状态管理方案]

频道:百科知识 日期: 浏览:0

Bitget下载

注册下载Bitget下载,邀请好友,即有机会赢取 3,000 USDT

APP下载   官网注册

很多朋友在找时都会咨询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状态管理的信息别忘了在本站进行查找喔。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 931614094@qq.com 举报,一经查实,本站将立刻删除。

本文地址: http://www.lyw520.com/baikezhishi/37135.html
文章来源: 小美
flutter状态管理[flutter状态管理方案]文档下载: PDF DOC TXT