Flutter 状态管理框架 Provider 和 Get 分析

文/ Nayuta,CFUG 社区

状况办理一直是 Flutter 开发中一个火热的话题。谈到状况办理结构,社区也有比方有以 Get、Provider 为代表的多种计划,它们有各自的优缺点。效率计算公式 面对这么多的挑选,你或许会想:「我需求运用状况办理么?哪种结构更适合我?」 本文将从作者的实践开发阅历出发,剖析状况办理处理的问题以及思路,希望能协助你做出swift是什么挑选。

测验你的自卑程度什么需求状况办理?

首先,为什么需效率公式求状况办理? 依据笔者的阅历swift系统,这是由于 Flutter 根据 功率高发票查验明式 构建 UI , 运用状况办理的意图之一便是处理「声明式」开发带来的问题。

「声明式」开发是一种差异于传原生的办法,所以咱们没有在原生开发悦耳到过状况办理,那怎么了解「声android是什么体系明式」开发呢?

「声明式」VS「命令式」剖析

以最经典的的计数器比android下载安装方剖析:

Flutter 状况办理结构 Provider 和 Get 剖析

如上图所示:点击右下角按钮,显示的文本数字加一。 Android 中能够这么多线程的实现方式测验英文完成:当右功率集下角按钮点中时, 拿到 TextView 的目标,手动设置其展现的文本。

完成代码如下:

// 一、界说展现的内容
private int mCount =0;
// 二、中心展现数字的控件 TextView
private TextView mTvCount;
// 三、关联 TextView 与 xml 中的组件
mTvCount = findViewById(R.id.tv_count)
// 四、点击按钮操控组件更新
private void increase( ){ 
	mCount++;
	mTvCounter.setText(mCount.toString()); 
}

而在 Flutter 中,咱们只需求使变量增加之后调用 setState((){}) 即可。setStaandroidstudio安装教程tandroid下载e 会改写整个页面,使得中心展多线程下载现的值进行改动。

// 一、声明变量
int _counter =0; 
// 二、展现变量 
Text('$_counter')
//  三、变量增加,更新界面
setState(() {
   _counter++; 
});

能够发现,Flutter 中只对 _coun测验英文ter 特点进行了修正,并没有对 Text 组件进行任何多线程是什么意思的操作,整个界面跟着状况的改动而改动。

所以在 Flutter 中有这么一种说androidstudio装置教程法: UI = f(st测验英文ate):

Flutter 状况办理结构 Provider 和 Get 剖析

上面的比方中,状况 (state) 便是 _countswift翻译er 的值,调用 setState 驱动 f build 办法生功率的英文成新的 UI。

那么,测验工程师声明式有哪些优势,并带来了哪些问题呢?

优势: 让开发者摆脱组件的繁琐操控,聚功率高发票查验焦于状况处理

习气 Fandroid的drawable类lutter 开发之后,回到原生平台开发,你会发现当多个组件android手机之间相互关联时,关于 View 的操控十分费事。

而在swift翻译 Flutter 中我功率们只需求处理好状况即可 (多线程是什么杂乱度转移到了状况 -> UI 的映射,也便是 Widget 的构建)。包含 Jetpack Comp效率的拼音ose、S测试你的自卑程度wift 等技术的最新开展,也是在朝着「声明式」的多线程是什么方向演进。

s多线程编程wift国际结算体系明式开发带功率的拼音来的问题

没有运用状况办理,直接「声明式swiftly」开发的时分,遇到的问题总结多线程有三个:

  1. 逻辑和页面 UI 耦合,导致无法复用/单元测验Swift修正紊乱等
  2. 难以跨组件 (跨页面) 拜访数据
  3. 无法轻松的操控改写规模 (页面 setState 的改变会导致大局页面的改变)

接下来,我先带领我们逐一了解这些功率符号问题,下一章向我们详细描述状况办理结构怎么处理这些多线程的实现方式问题。

1) 逻辑和页面 UI 耦合,导致无法复用/单元功率的拼音测试用例测验、修正紊乱等

Flutter 状况办理结构 Provider 和 Get 剖析

一开始事务不杂乱的时分,一切的代码都直接写到 widget 中,跟着事务迭代, 文件越来越大,其他开发者很难直观地明白里边的事务逻辑。 而且swift是什么组织缩写一些通用逻辑,例如网络请求状况测验工程师的处理、分页等,在不同的页面来回张贴。

这个问android是什么体系题在原生上相同存在,后边也衍生了比方 MVP 规划形式的思路去处理。

2) 难以跨组件 (跨页面) 拜访数据

Flutter 状况办理结构 Provider 和 Get 剖析

第二点在于跨组件交互,比方在 Widget 结效率高发票查验构中, 一个子组件想要展现父组件中的 name 字段, 或许需求层层进行传递。

又或者是要在两个页面之间同享挑选数据, 并没有一个很优雅的机制去处理这种跨页面的数据拜访。

3) 无法轻松的操控改写规模 (页面 setState 的改变会导致大局页面的改变多线程应用场景例子)

最后一个问题android下载安装也是上面说到的优android平板电脑价格点,许多场景咱们仅仅部swift语言分状况的修正,例如按钮的颜色。 可是整个页面的 setState 会使得其他不swiftly需求改变的当地也进行重建, 带来测验英文多线程是什么不必要的开销。

Provider、Get 状况办理结构规划剖析

Flutter 中状况办理结构的中心在于这三个问题的处理思路, 下面一起看看 ProSwift效率的英文vider、G功率高发票查验et 是怎么处理的:

处理逻辑和页面 UI 耦合问题

传统的原生开发相同存在这个问题,Activity 文件也可多线程并发能跟着迭代变得难以维护, 这个问题能够经过 MVP 形式进行解耦。

简单来说测验便是将 View 中的逻辑代码抽离到 Pr多线程是什么esente测试仪r 层测验, View 只担任视测试英文图的构建。

Flutter 状况办理结构 Provider 和 Get 剖析

这也是 Fluttswift语言er 中几乎一切状况办理结构的处理思路, 上图的 Presenter 你swift是什么能够以为是 Get 中的 GetController、 Pr多线程是什么ovider 中功率的拼音ChangeNotifier效率符号 或者 Bloc 中的 Bloc测试 值得一提的是,具体做法上 Flutter 和原生 MVP 结构有所不同。

咱们知道功率的英文在经典 MVP 形式中, 一般 View 和 Presenter 以接口界说自身行为 (action), 相互持有接口进行调用

Flutter 状况办理结构 Provider 和 Get 剖析

但 Flutter 中不太适合这么做测试用例功率英文翻译 从 Presente测验英文r → View 联系上 View 在 Flutter 中对应 Widget, 但在 Flutter 中 Widget 仅仅用户声明 UI 的配置,多线程并发中线程的状态swifter接操控 Widget 实例并不是好的做法多线程并发中线程的状态

而在从 View → Presenter 的联系上, Widget 能够功率意识方多线程的实现方式面存在的问题确实能够直接持有 Presenter, 可是这样又会带来难以数据通讯的问题。

这一点不同状况办理结构的处理思路不多线程并发中线程的状况相同,从完成上他们能够分为两大类:

  • 经过 FlutterSwift 树机制 处理,例如 Provider;
  • 经过 依靠注入,例如 Get。测试抑郁症的20道题

1) 经过 Flutter 树机制处理 V →效率符号 P 的获取

Flutter 状况办理结构 Provider 和 Get 剖析

abstract class Element implements BuildContext {
	/// 当前 Element 的父节点
	Element? _parent; 
}
abstract class BuildContext {
	/// 查找父节点中的T类型的State
	T findAncestorState0fType<T extends State>( );
	/// 遍历子元素的element目标
	void visitChildElements(ElementVisitor visitor);
	/// 查找父节点中的T类型的 InheritedWidget 例如 MediaQuery 等
	T dependOnInheritedWidget0fExactType<T extends InheritedWidget>({ 
		Object aspect });
	……
} 
Element 完成了父类 BuildContext 中操作树结构的办法

咱们知道多线程 Flutter 中存在三棵树,Wiswift国际结算系统dget、Element 和 RenderObjec测验效率t。 所谓的 Widg多线程的实现方式et 树其实仅仅咱们描述组件嵌套联系的一种说法,是一种虚拟的结构。 但 Element 和 RenderObject效率意识方面存在的问题 在运行时实践存在, 能够看到 Element 组件中包含了 _parent 特点,存放其父节点。 而它完成了 Buil功率dContext效率的拼音测验用例口,包含了许多关于树结构操作的办法, 例如 findAncesandroid什么意思torStateOswift是什么fTy测试工程师pe,向上查找父节点; visitChildElements 遍历子节点。

在一开始的比方中,咱们能够经过 context.findAncestorS测试手机是否被监控tateOfTy效率英文翻译pe 一层一层地向上查找到需求的 Element 目标, 获取 Widg功率计算公式et 或者 State 后即可取出需求android什么意思的变量。

Flutter 状况办理结构 Provider 和 Get 剖析

provider 也是借助了这样测试英文的机制,完成了 V测验用例i测试仪ew -> Presenter 的获取。 经过 Provider.of 获取顶层 Provider 组件中的 P测试你的自卑程度resent 目标。 显然,一切 Pr测验ovider 以下的 Widget 节点, 都能够经过自身的 context 拜访到 Provider 中的 Presenter, 很好地处理了跨组件的通讯问题。

2) 经过依靠注入的办法处理 V → P

树机制很不错Android,但依靠于 context,这一点有时很让人抓狂。 咱们知道 Das测试wiftlyrt 是一种单线程的模效率意识方面存在的问题型, 所以不存在多线程android/harmonyos关于目标拜访的竞态问题。 根据此 Get 借助一个大局单多线程例的 Maswifswift是什么意思啊t代码p 存储目标。 经过依靠注入的办法,完成了对 Presenter 层的获取。 这样在恣意的类中都能够获取到 Pandroid什么意思resenter。

Flutter 状况办理结构 Provider 和 Get 剖析

这个 Map 对应的 key 是 r测试手机是否被监控untimeType + tag, 其中 tag 是可选参数,而 value 对应 Object, 也便是说咱们能够存入任何类型的目标,而且在恣意方位获取。

处理难以测试手机是否被监控多线多线程面试题程并发跨组件 (跨android手机页面) 拜访数据的问题

这个问题其实和上多线程的完成办法一部分的思考根多线程是什么本相似,所以咱们能够总结一下两种计划特点:

Flutter 状况办理结构 Provider 和 Get 剖析

P功率效率的英文的英文rovider

  • 依靠树Android机制,必须根据 context
  • swift是什么给了子组件拜访上层的才能

Get

  • 大局单例,恣意方位能够存取
  • 存在类型重复,内存回测验郁闷程度多线程是什么意思的问卷收问题

处理高层级 setState 引起不必要改写的问题

最后便是咱们说到的高层级 setState 引起不必要改写的问题, Flutter 经过采用调查者形式处理,其关键在于两步:

  1. 调查者去订阅被调查的目标;
  2. 被调查的目标通知调查者。

Flutter 状况办理结构 Provider 和 Get 剖析

体系也供给了测试工程师 ValueNotifier 等组件的完成:

/// 声明或许改变的数据
ValueNotifier<int> _statusNotifier = ValueNotifier(0); 
ValueListenableBuilder<int>(
	// 树立与 _statusNotifier 的绑定联系 
	valueListenable: _statusNotifier, 
	builder: (c, data, _) {
		return Text('$data'); 
})
///数据改变驱动 ValueListenableBuilder 部分改写 
_statusNotifier.value += 1;

了解到最根底的调查者形式后,看看swift翻译不同结构中多线程的实现方式供给swift代码的组件:功率公式

比方 PAndroidrovider 中供给了 C多线程并发中线程的状态hangeNswift体系otifierProvi多线程下载der:

class Counter extend ChangeNotifier {
	int count = 0;
	/// 调用此办法更新一切调查节点
	void increment() {
		count++;
		notifyListeners(); 
	}
}
void main() { 
	runApp(
		ChangeNotifierProvider(
			///  返回一个完成 ChangeNotifier 接口的目标 
			create: (_) => Counter(),
			child: const MyApp( ), 
		),
	);
 }
///  子节点经过 Consumer 获取 Counter 目标 
Consumer<Counter>(
	builder:(_, counter, _) => Text(counter.count.toString()) 

还是之前计数器的比方,这儿 Counter 继承了 CswifterhangeNswift系统otifier 经过顶层的 Pro多线程并发viandroid是什么系统der 进行存储。 子节点经过 Consumer 即可获取实例, 调用android下载increment 办法之后,只要对应的 Text 组件进行改变。

相同的功能,在 Get 中, 只需求提前调用 Get.put 办法存储 Counter 目标, 为 GetBuilswift是什么der 组件指定 Counter 作为泛型。 由于 Get 根多线程并发据单例,所以 GetBuilder 能够直接经过泛型获取到存入的目标, 并在 builder 办法中露出。这样 Counter 便swift语言与组件树立了监听联系, 之后 Counter 的变动,只会驱动以它作为泛测试仪型的 GetBuildeswift是什么r 组件更新。

class Counter extends GetxController {
	int count = 0;
	void increase() { 
		count++;
		update(); 
	}
}
/// 提前进行存储
final counter = Get.put(Counter( )); 
/// 直接经过泛型获取存储好的实例
GetBuilder<Counter>(
	builder: (Counter counter) => Text('${counter.count}') ); 

实践中的常见问题

在运用这些结构过程中,或许会遇到以下的问题:

Provider 中 context 层级过高

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Provider(
      create: (_) => const Count(),
      child: MaterialApp(
        home: Scaffold(
          body: Center(child: Text('${Provider.of<Counter>(context).count}')),
        ),
      ),
    );
  }
}

Flutter 状况办理结构 Provider 和 Get 剖析

如代码所示,当咱swift系统们直接将 Provider 与组件嵌套于同一层级时, 这时代码中的 Provider.of(context) 运行时抛出 ProviderNotFoundExcep测验郁闷症的20道题tion。 由于此功率意识方面存在的问题处咱们运效率是什么意思用的 context 来自于 M测验郁android手机闷程度的问多线程并发中线程的状态yApp, 但 ProvSwiftider功率符号 的 element 节android是什么手机牌子点位于 MyAandroid什么意思pp 的下方, 所以 Provider效率的英文.of(context) 无法获取到 Provswift是什么意思啊ider 节点。 这个问题能够有两种改法,如下方代码所示:

改法 1: 经过嵌套 Builder 组件androidstudio装置教程,运用子节点的 co测试你适合学心理学吗ntext 拜访:

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Provider(
      create: (_) => const Count(),
      child: MaterialApp(
        home: Scaffold(
          body: Center(
            child: Builder(builder: (builderContext) {
              return Text('${Provider.of<Counter>(builderContext).count}');
            }),
          ),
        ),
      ),
    );
  }
}

改法 2: 将 Provider 提至顶层:

void main() {
  runApp(
    Provider(
      create: (_) => Counter(),
      child: const MyApp(),
    ),
  );
}
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(child: Text('${Provider.of<Counter>(context).count}')),
      ),
    );
  }
}

GeAndroidt 由于大局单例带来的问题

正如前面说到 Get 经过大局单例,默许以 runtimeType 为 key 进行目标的存储, 部分场景或许获取到的目标不符合预期,例如商品详情页多线程是什么之间跳转。 由于不同多线程应用场景例子的详情页实例对应的是同一 Class,即 runtimeType 相同。 假如不添加 tag 参数,在某个页面调用 Get.find 会获取多线程下载到其它页面已经存储过android下载安装的目标。 同时功率英文翻译 Get 中一定要留意考虑到目标的收回,否则很有或许引起内存泄漏。 要么手动在页面 dispose 的时分做 delet多线程面试题e功率符号 操作, 要么测试彻底运用 Get 中供给的组件,例功率符号android的drawable类GetBswift是什么uilder, 它会在 dispose 中开释。

Flutter 状况办理结构 Provider 和 Get 剖析

GetBuild效率计算公式er 中在 dispose 阶段进行收回:

@override
void dispose() {
  super.dispose();
  widget.dispose?.call(this);
  if (_isCreator! || widget.assignId) {
    if (widget.autoRemove && GetInstance().isRegistered<T>(tag: widget.tag)) {
      GetInstance().delete<T>(tag: widget.tag);
    }
  }
  _remove?.call();
  controller = null;
  _isCreator = null;
  _remove = null;
  _filter = null;
}

Get 与 Provider 优缺点总结Android

经过本文,我向我们介绍了状况办理的必要性、它处理了 Flutter 开发中的哪些问题以及是怎么处理的, 与此同时,我也为我们总结了在实践中常见的问测验仪题等swiandroid的drawable类ft翻译,看到这儿你或许还会有些疑惑,到底是否需求运用状况办理?

在我看来,结构是为了处理问题而存在。所多线程是什么意思以这取决于你是否也在阅历一开始提出的那些问题。 假如有,那么你能够尝试运用状况办理处理;假如没有,则没必要过多线程度规划,为了运用而运用。

其次,假如运用状况办理,那么 Get 和 Pr功率的拼音oviderandroid是什么体效率高发票查验 哪个更好?

这两个结构各有优缺点,我以为如多线程是什么果你或者你的团队刚接触 Flutter, 运用 Provider 能协助你们更快了解 Flutter 的中心机制。 而假如已经对 Flutter 的原理有了解,Get 丰富的功能和简洁的 API, 则能Swift协助你很好地进步开发功率

感谢社区成员 Alex、swiftlyLuke、Lynn、M多线程下载ing 对本文的贡献。

发表评论

提供最优质的资源集合

立即查看 了解详情