文章系列
Flutter Provider状态管理---介绍、类图分析、基本使用
Flutter Provider状态管理---八种提供者使用分析
Flutter Provider状态管理---四种消费者使用分析
Flutter Provider状态管理---MVVM架构实战
视频系列
Flutter Provider状态管理---介绍、类图分析、基本使用
Flutter Provider状态管理---八种提供者使用分析
Flutter Provider状态管理---四种消费者使用分析
Flutter Provider状态管理---MVVM架构实战
源码仓库地址
介绍
Provider
是一个由社区构建的状态管理包,而不是Google
推出,但Provider
是Google
极力推荐的状态管理方式之一,它是对InheritedWidget
组件进行了封装,使其更易用,更易复用。
学习本章节前,希望你能了解如下知识:
- 熟悉dart语言
- 熟悉flutter基本组件
- 了解InheritedWidget
- 了解ChangeNotifier
如果大家大家之前没接触过InheritedWidget
,那么建议你先去了解,你可以通过链接来查看并掌握对应的只是 英文官方文档 中文官方文档 源码分析 视频教程
Provider优势
我们为什么要用Provider
而不是直接使用InheritedWidget
,我们看下官方介绍
- 简化的资源分配与处置
- 懒加载
- 创建新类时减少大量的模板代码
- 支持 DevTools
- 更通用的调用 InheritedWidget 的方式(参考 Provider.of/Consumer/Selector)
- 提升类的可扩展性,整体的监听架构时间复杂度以指数级增长(如 ChangeNotifier, 其复杂度为 O(N))
Provider类结构图
Provider类说明
Nested组件
- Nested: 简化树结构嵌套过深
-
SingleChildWidget: 单个子组件的组件,但是它与
ProxyWidget
不同,有一个build
方法。 -
SingleChildStatelessWidget: 它是一个实现
SingleChildWidget
的StatelessWidget
,必须使用buildWithChild
构建子组件 -
SingleChildStatefulWidget: 它是一个实现
SingleChildWidget
的StatefulWidget
,是与Nested
兼容的StatefulWidget
Provider组件
Provider
组件分为四大类,分别如下:
Nested系列
MultiProvider: 主要作用是提高代码可读性和减少重复代码,是将多个提供者合并成单个线性的组件提供者。
SingleChildStatefulWidget系列
- Selector0: 它是Selector至Selector6的基类
-
Selector1-6: 它们是将
Selector0
与Provider.of
结合使用的语法糖,继承自Selector0
SingleChildStatelessWidget系列
-
Consumer1-6: 消费者,只是调用了
Provider.of
,主要作用是从顶层获取Provider<T>
并将其值传递给了builder
。 -
InheritedProvider:
InheritedWidget
的通用实现,并且所有的继承自该类的都可以通过Provider.of
来获取value
-
DeferredInheritedProvider:
InheritedProvider
的子类,用于监听流或者接收一个Future
- StreamProvider: 监听流,并暴露出当前的最新值。
-
FutureProvider: 接收一个
Future
,并在其进入complete
状态时更新依赖它的组件。 -
ListenableProvider: 供可监听对象使用的特殊
provider
,ListenableProvider
会监听对象,并在监听器被调用时更新依赖此对象的widgets
。 -
ChangeNotifierProvider: 为
ChangeNotifier
提供的ListenableProvider
规范,会在需要时自动调用ChangeNotifier.dispose
。 - ListenableProxyProvider0: 可见的代理提供者,主要是从其他提供者获取值。
-
ListenableProxyProvider1-6: 它是
ListenableProvider
的一个变体,继承ListenableProxyProvider0
, 从其他提供者获取值 -
ChangeNotifierProxyProvider0: 主要用于构建和同步
ChangeNotifier
的ChangeNotifierProvider
。 - Provider: 最基础的 provider 组成,接收一个任意值并暴露它。
-
ProxyProvider0: 它公开的值会通过创建或更新构建,然后传递给
InheritedProvider
。 -
ProxyProvider1-6:
ProxyProvider0
的语法糖。
InheritedContext系列
-
InheritedContext: 与
InheritedProvider
关联的BuildContext
,提供公开的值 - ReadContext: 公开读取方法
- SelectContext: 在 BuildContext 上添加一个选择方法。
- WatchContext: 公开 watch 方法。
Provider基本使用
第一步:添加依赖
本文中所有的代码都是基本空安全的,所有dart sdk版本为>=2.12.0 <3.0.0
,目前官方最新版本为^6.0.1
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
provider: ^6.0.1
第二步:定义需要共享的数据
我们这里创建了一个类CountNotifier
继承了ChangeNotifier
,我们这里的案例是以计数器为案例,所有我们定义一个变量count
,以及一个改变数值的increment
方法,当我们调用increment
后会对count
进行+1,最后调用notifyListeners()
来更新数据,代码如下:
import 'package:flutter/material.dart';
class CountNotifier with ChangeNotifier {
int count = 0;
void increment() {
count++;
notifyListeners();
}
}
第三步:在应用程序入口初始化
我们在MaterialApp
之前对定义的共享数据进行了初始化,代码如下:
import 'package:flutter/material.dart';
import 'package:flutter_provider_example/provider_count_example/count_notifier.dart';
import 'package:flutter_provider_example/provider_count_example/provider_count_example.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => CountNotifier(),
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: ProviderCountExample(),
),
);
}
}
第四步:使用共享数据
我们定义了一个counter
变量来获取到共享的数据,更新数据的方法直接通过counter.increment()
,获取数据的方法通过ounter.count.toString()
来获取,代码如下:
import 'package:flutter/material.dart';
import 'package:flutter_provider_example/provider_count_example/count_notifier.dart';
import 'package:provider/provider.dart';
class ProviderCountExample extends StatefulWidget {
@override
_ProviderCountExampleState createState() => _ProviderCountExampleState();
}
class _ProviderCountExampleState extends State<ProviderCountExample> {
@override
Widget build(BuildContext context) {
final counter = Provider.of<CountNotifier>(context);
return Scaffold(
appBar: AppBar(
title: Text("InheritedWidget"),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
counter.increment();
},
child: Icon(Icons.add),
),
body: Center(
child: Text(counter.count.toString(),
style: TextStyle(
color: Colors.red,
fontSize: 50
),
),
),
);
}
}
总结
以上是对Provider
进行了介绍、优势、类结构和说明以及一个基本使用的例子,相对于使用InheritedWidget
来说,显然Provider
使用起来更简单。但是从它的提供者、消费者这些类来看稍微复杂,后面的章节中我们来讲讲这些类