这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战
Selector<A, S>
相当于 Consumer 可以通过选择有限数量的值来过滤更新,并在它们没有更改时防止重建。
Selector 将使用 Provider.of 获取一个值,然后将该值传递给 selector。然后,该selector
回调的任务是返回一个对象,该对象仅包含builder
所需的信息。
Selector 源码:
class Selector<A, S> extends Selector0<S> {
/// {@macro provider.selector}
Selector({
Key? key,
required ValueWidgetBuilder<S> builder,
required S Function(BuildContext, A) selector,
ShouldRebuild<S>? shouldRebuild,
Widget? child,
}) : super(
key: key,
shouldRebuild: shouldRebuild,
builder: builder,
selector: (context) => selector(context, Provider.of(context)),
child: child,
);
}
示例:
这里使用了 mixin 混入了 ChangeNotifier,这个类能够帮驻我们自动管理所有听众。 当调用 notifyListeners() 时,它会通知所有监听者进行刷新。
import 'package:flutter/material.dart';
class CountModel with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
UI相关代码: value : 是下面 selector的返回值
Selector<UserModel, int>(
builder: (BuildContext context, value, Widget child) {
return Row(
children: [
child,
Text('$value'),
],
);
},
selector: (BuildContext context, UserModel userModel) {
return userModel.count;
},
child: Text(['count:'),
),
主要记录一下参数相关的东西:
- A 指的是model , 或者叫provider (指with/extend ChangeNotifier的那个类),示例中的
CountModel
. - S selector参数中的返回类型 , 一般为 model中维护的数据 .
如例子中的
count
的类型int
. 也可以是Wdiget
, 比如你在这里返回一个Text, 就可以在builder
中直接使用
builder: (BuildContext context, value, Widget child) {
return Row(
children: [
child,
value,
],
);
},
selector: (BuildContext context, UserModel userModel) {
return Text('${userModel.count}');
},
typedef ValueWidgetBuilder<T> = Widget Function(BuildContext context, T value, Widget? child)
T : selector的返回值的类型 , 其实是ValueWidgetBuilder<S>
中的S
.S Function(BuildContext, A) selector
A
: 同上文typedef ShouldRebuild<T> = bool Function(T previous, T next)
S
: 同上文 ,其实是ShouldRebuild<S>? shouldRebuild
中的S
理解了以上这些概念,使用的时候就不会懵逼了 .
Selector的好处 :
- 减少UI重绘的部分, 提升性能 . 当监听到数据变更时, 只会重新调用builder.不会重绘更多UI部分.
- 默认情况下,Selector通过使用来自包集合的 DeepCollectionEquality 比较Selector的先前和新结果来确定是否需要再次调用builder。(可以通过传递自定义的 shouldRebuild 回调来覆盖此行为。)