Provider 是一个用来提供数据的框架。它是 InheritedWidget 的语法糖,提供了依赖注入的功能,允许在 Widget 树中更加灵活地处理和传递数据。
那么,什么是依赖注入呢?通俗地说,依赖注入是一种可以让我们在需要时提取到所需资源的机制,即:预先将某种“资源”放到程序中某个我们都可以访问的位置,当需要使用这种“资源”时,直接去这个位置拿即可,而无需关心“资源”是谁放进去的。
在使用之前首先需要在 pubspec.yaml 文件中添加 Provider 的依赖
dependencies:
flutter:
sdk: flutter
# 状态管理
provider: ^4.3.2+2
数据状态封装
//定义需要共享的数据模型,通过混入ChangeNotifier管理听众
class CounterModel with ChangeNotifier {
int _count = 0;
//读方法
int get counter => _count;
//写方法
void increment() {
_count++;
notifyListeners();//通知听众刷新
}
}
我们在资源封装类中使用 mixin 混入了 ChangeNotifier。这个类能够帮助我们管理所有依赖资源封装类的听众。当资源封装类调用 notifyListeners 时,它会通知所有听众进行刷新。
资源注入
因为 Provider 实际上是 InheritedWidget 的语法糖,所以通过 Provider 传递的数据从数据流动方向来看,是由父到子。so 只需要把资源放到 需调用资源的Widget 的父 Widget中
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
//通过Provider组件封装数据资源
return ChangeNotifierProvider.value(
value: CounterModel(),//需要共享的数据资源
child: MaterialApp(
home: FirstPage(),
)
);
}
}
ChangeNotifierProvider:为子Widget提供读写能力
Provider:只为子 Widget 提供读能力
MultiProvider:提供多资源依赖注入
资源获取
最简单的就是用 Provider.of<T>(),
//取出资源
final _counter = Provider.of(context);
但是,滥用 Provider.of 方法也有副作用,那就是当数据更新时,页面中其他的子 Widget 也会跟着一起刷新。
使用 Consumer 精准控制 UI 刷新粒度
Consumer 使用了 Builder 模式创建 UI,收到更新通知就会通过 builder 重新构建 Widget。
floatingActionButton: Consumer( //builder函数可以直接获取到increment参数
builder: (context, CounterModel counter, child) => FloatingActionButton(
onPressed: counter.increment,
child: child,
),
child: TestIcon(),
),
Consumer 中的 builder 实际上就是真正刷新 UI 的函数,它接收 3 个参数,即 context、model 和 child。其中:context 是 Widget 的 build 方法传进来的 BuildContext,model 是我们需要的数据资源,而 child 则用来构建那些与数据资源无关的部分。在数据资源发生变更时,builder 会多次执行,但 child 不会重建。
网友评论