前言
setState调用这个方法会导致整个页面重绘,如果页面比较复杂,可以使用官方推荐的provider包。它允许通过一个中心组件来传递和共享数据。它使用了InheritedWidget,建立了一个数据传递的上下文树来实现数据共享。
Provider
常见类型:
- MultiProvider:用于在一个组件中共享多个不同类型的Provider。它可以简化在一个组件中使用多个Provider的情况。
除了这些内置的Provider类型,Provider还提供了一些辅助类和功能,以便更好地组织和管理共享数据。例如:
- Provider.of:用于从Provider中获取共享数据。
- Provider.listen:用于监听共享数据的变化。
- Consumer和Selector:用于在UI中订阅共享数据的变化,并更新相应的UI。
安装
添加依赖,命令安装
flutter pub add provider
或者在pubspec.yaml中添加
dependencies: provider: ^6.1.2
用法
1、注册provider提供数据
void main() {
runApp(ChangeNotifierProvider(
create:(context) => CounterProvider(),
child: const MyProvider(),
));
}
不建议在程序入口使用Provider,可在指定页面使用。 可以使用 MultiProvider 来同时提供多个 Providers
void main() {
runApp(MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => CounterProvider()),
ChangeNotifierProvider(create: (context) => CounteModel())],
child: const MyProvider(),
));
}
另外当按照官方推荐写法时报错:
Provider(
create: (_) => MyModel(),
child: ...
)
不知道为什么,欢迎各位同学指点。
2、CounterProvider
数据模型类
import 'package:flutter/material.dart';
class CounterProvider extends ChangeNotifier {
int _count = 0;
int get value => _count;
void increment() {
_count++;
notifyListeners(); // 通知监听者数据变化
}
}
继承ChangeNotifier, 初始化count,并提供一个get方法; 调用increment方法,会触发notifyListeners,这里会通知CounterProvider的订阅者更新UI。
3、MyProvider
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: Text("value = ${counterProvider.value}"),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.navigation),
onPressed: (){
counterProvider.increment();
},
),
);
}
}
Provider.of() 可以获取共享实例对象,但是调用的widget会被重建。Provider.of() 有一个参数listen默认值为true,如果想在build()中访问状态,可以设置 listen: false 以减少不必要的重建。
Consumer
通过更细粒度的重构来帮助性能优化
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, _) {
return Text("value3 = ${counterProvider.value}");
},
),
),
floatingActionButton: Consumer(
builder: (context, CounterProvider counterProvider, _) {
return FloatingActionButton(
child: const Icon(Icons.navigation),
onPressed: () {
counterProvider.increment();
},
);
},
),
);
}
}
Consumer的child参数,可以将不需要更新重建的组件放在这里,减少重绘,提升性能。