Flutter Provider状态管理的八种提供者、四种消费者(下)
文章目录
前言
作者的整理了Provider状态管理的八种提供者和四种消费者的介绍和使用。这篇文章可以告诉你Provider到底是个什么,如何使用。作者能力有限该文章不涉及源码的讲解!建议先去了解一下Buildcontext context(Element)的作用便于理解。
Provider的八种提供者
Flutter Provider状态管理的八种提供者、四种消费者(上)
Provider的四种消费者
一、Provider.of
static T of<T>(BuildContext context, {bool listen = true}) {
assert(
context.owner!.debugBuilding ||
listen == false ||
debugIsInInheritedProviderUpdate,
,
);
final inheritedElement = _inheritedElementOf<T>(context);
if (listen) {
context.dependOnInheritedWidgetOfExactType<_InheritedProviderScope<T?>>();
}
final value = inheritedElement?.value;
if (_isSoundMode) {
if (value is! T) {
throw ProviderNullException(T, context.widget.runtimeType);
}
return value;
}
return value as T;
}
static _InheritedProviderScopeElement<T?>? _inheritedElementOf<T>(
BuildContext context,
) {
assert(context != null, '''
''');
assert(
_debugIsSelecting == false,
);
assert(
T != dynamic,
);
final inheritedElement = context.getElementForInheritedWidgetOfExactType<
_InheritedProviderScope<T?>>() as _InheritedProviderScopeElement<T?>?;
if (inheritedElement == null && null is! T) {
throw ProviderNotFoundException(T, context.widget.runtimeType);
}
return inheritedElement;
}
具体使用
Text(Provider.of<CountNotifier1>(context).count.toString(),
style: TextStyle(
color: Colors.red,
fontSize: 50,
),
),
Provider,of 通过BuildContext context, {bool listen = true} 默认参数 去监听参数,使用context调用上级CountNotifier(T类型模型)的数据。如果不知道为什么的,需要了解一下BuildContext context。
如果需要从Widget树外部监听提供者公开的值,需要设置为listen = false。
二.Cousumer
Consumer只是在widget中调用了Provider.of ,并将其构造实现委托给了构造器,比如我们常见的Builder,如果你的Widget依赖多个模型,那么它还提供了Cousumer23456方便使用。

Consumer有三个参数,Key,Builder ,和一个 child(子widget)

代码如下(示例):
Consumer<UserModel1>(
builder : (_,userModel,child){ // _ 为Buildercontext context
return Text(userModel.name,
style: TextStyle(
color: Colors.red,
fontSize: 30,
),
);
},
),
);
2代表模型的个数 还有3456可以使用
Consumer2<UserModel1,UserModel4>(
builder: (_,userModel1,userModel4,child){
return Padding(
padding: EdgeInsets.all(20),
child: ElevatedButton(
onPressed: (){
userModel4.changeName();
userModel1.changeName();
},
child: Text("改变值"),
),
);
},
该处使用的url网络请求的数据。
当然如果要child需要单独的声明来保证该参数不为空
三.Selector
Selector和Consumer类似,只是对Build调用widget方法时提供更精细的控制,简单点来说,Selector也是一个消费者,它允许你可以从模型中准备定义那些属性。

两个必选参数


代码如下(示例):
child: Selector<UserModel6, int>(
selector: (_,userModel6) => userModel6.age, // int age
builder: (_,age,child){
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(age.toString(),
style: TextStyle(
color: Colors.red, fontSize: 38,
),
),
child
],
);
},
child: Padding(
padding: EdgeInsets.all(20),
child: ElevatedButton(
onPressed: (){
Provider.of<UserModel6>(context,listen: false).increaseAge();
},
child: Text("改变年龄"),
),
),
Selector依旧支持多个选择 有Selector23456
四.InherContext
InheritedContext是provider内置扩展了BuildContext,它保存了组件在树中自己位置的引用,我们在上面的案例中见到Provider.of(context,listen : false),其实这个of方法就是使用Flutter查找树并找到Provider子类型为CountNotifier而已
三大方式
BuildContext.read:
BuildContext.read可以替换掉Provider.of(context,listen : false) ,它会找到CountNotifier返回

所以可见 read()就是调用了Provider.of(this,listen: false);
BuildContext.watch:
BuildContext.watch可以替换掉Provider.of(context,listen : false) ,看起来和read没有什么不同,但是使用watch你就不需要使用Consumer。

listen: 默认为true;
BuildContext.select:
BuildContext.read可以替换掉Provider.of(context,listen : false) ,看起来和Watch也没有什么不同,但是使用select你就不需要再使用Selector
R select<T, R>(R Function(T value) selector)
ListView.builder(
itemBuilder: (context, index) {
return Builder(builder: (context) {
final todo = context.select((TodoList list) => list[index]);
return Text(todo.name);
});
},
);
总结
祝大家乘风破浪
942

被折叠的 条评论
为什么被折叠?



