前言
Selector是比Consumer更细颗粒度的管理方式,Consumer可以监听Provider所有数据变化,而Selector可以监听一个或者多个数据的变化。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_drive/counter_provider.dart';
class MyProvider extends StatefulWidget {
const MyProvider({super.key});
@override
State<MyProvider> createState() => _MyProviderState();
}
class _MyProviderState extends State<MyProvider> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Consumer<CounterProvider>(
builder: (context, counterProvider, _) {
print("Text展示调用");
return Text("value3 = ${counterProvider.value}");
},
),
),
floatingActionButton: Consumer(
builder: (context, CounterProvider counterProvider, _) {
print("FloatingActionButton调用");
return FloatingActionButton(
child: const Icon(Icons.navigation),
onPressed: () {
counterProvider.increment();
},
);
},
),
);
}
}
当点击FloatingActionButton时,会打印
I/flutter ( 5378): FloatingActionButton调用
I/flutter ( 5378): Text展示调用
说明两个位置都会被builder,而floatingActionButton位置只是调用方法,并没有展示,没有必要重新build,所以可以使用使用Selector来代替Consumer
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,
);
}
Selector提供了builder,selector,shouldRebuild和child四个属性,selector和builder属于必选项。
1、selector属性
方法中包含两个参数,方法返回转换后的数据类型,函数原型为S Function(BuildContext, A) selector
- BuildContext:主要用来创建Widget,为创建Widget提供上下文环境;
- A:它是泛型类型,它用来表示共享数据对象,通过该对象的getter方法可以获取到共享数据,然后就可以转换数据类型;
- S:它是泛型类型,它用来表示转换数据类型后的对象,它和builder属性中的第二个参数类型相同;
2、builder属性
方法中包含三个参数,方法返回Widget对象。 该方法中三个参数如下:
- context:主要用来创建Widget,为创建Widget提供上下文环境;
- value:是泛型类型,它用来表示转换数据类型后的对象;
- child:表示Selector组件的子组件,因此它代表的对象和Selector组件的child属性代表的对象相同;
3、shouldRebuild属性
方法中包含两个参数,方法返回true或者false.返回值表示是否更新组件以及组件中的共享数据。该属性是可选属性,默认返回false。
- previous:它是泛型类型,它用来表示转换前数据类型的对象;
- next:它是泛型类型,它用来表示转换后数据类型后的对象;
注意:这两个属性的类型相同,表示把共享数据类型转换后的数据类型,也就是selecttor属性中的S。
使用
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_drive/counter_provider.dart';
class MyProvider extends StatefulWidget {
const MyProvider({super.key});
@override
State<MyProvider> createState() => _MyProviderState();
}
class _MyProviderState extends State<MyProvider> {
@override
Widget build(BuildContext context) {
// CounterProvider counterProvider = Provider.of<CounterProvider>(context);
return Scaffold(
body: Center(
child: Consumer<CounterProvider>(
builder: (context, counterProvider, _) {
print("Text展示调用");
return Text("value3 = ${counterProvider.value}");
},
),
),
floatingActionButton: Selector<CounterProvider,CounterProvider>(
selector: (context,provider) => provider,
shouldRebuild: (previous, next) => false,
builder: (context, counterProvider, _) {
print("FloatingActionButton调用");
return FloatingActionButton(
child: const Icon(Icons.navigation),
onPressed: () {
counterProvider.increment();
},
);
},
),
);
}
}
再次点击FloatingActionButton时,只会打印“Text展示调用”
总结
使用Selector可以减少不必要的 widget 重建,提升应用的响应速度和流畅度。