final counterStateProvider = StateProvider<int>((_) => 0); classCounterWidgetextendsConsumerWidget{ @override Widget build(BuildContext context, WidgetRef ref) { // 1. watch the provider and rebuild when the value changes final counter = ref.watch(counterStateProvider); return ElevatedButton( // 2. use the value child: Text('Value: $counter'), // 3. change the state inside a button callback onPressed: () => ref.read(counterStateProvider.notifier).state++, ); } }
final counterStateProvider = StateProvider<int>((_) => 0);
classCounterWidgetextendsConsumerWidget{ @override Widget build(BuildContext context, WidgetRef ref) { // if we use a StateProvider<T>, the type of the previous and current // values is StateController<T> ref.listen<StateController<int>>(counterStateProvider.state, (previous, current) { // note: this callback executes when the provider value changes, // not when the build method is called ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Value is ${current.state}')), ); }); // watch the provider and rebuild when the value changes final counter = ref.watch(counterStateProvider); return ElevatedButton( // use the value child: Text('Value: $counter'), // change the state inside a button callback onPressed: () => ref.read(counterStateProvider.notifier).state++, ); } }
final tmpProvider = StateProvider.autoDispose<int>((ref){
// get the [KeepAliveLink] final link = ref.keepAlive(); // start a 30 second timer final timer = Timer(constDuration(seconds: 30), () { // dispose on timeout link.close(); }); // make sure to cancel the timer when the provider state is disposed // (prevents undesired test failures) ref.onDispose(() => timer.cancel());
return1; });
我们可以使用extension封装一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
extension AutoDisposeRefCache on AutoDisposeRef { void cacheFor(Duration duration) { final link = keepAlive(); final timer = Timer(duration, () { link.close(); }); onDispose(() { timer.cancel(); }); } }
//使用 final timerCachedProvider = Provider.autoDispose<int>((ref) { ref.cacheFor(Duration(minutes: 5)); return1; });
family
我们可以用它向 Provider 提供参数,比如我们的计数器示例,比如想从指定的数字开始
1 2 3 4 5
final countProviderBase = StateProvider.autoDispose.family<int,int> ((ref,start){ return start; }); //使用 final startValue = ref.watch(countProviderBase(10));
final spProvider = Provider<SharedPreferences>((ref) { return SharedPreferences.getInstance();//不可以这样使用 //The return type 'Future<SharedPreferences>' isn't a 'SharedPreferences', as required by the closure's context. });
这时候我们可以先抛出一个为实现的异常
1 2 3
final sharedPreferencesProvider = Provider<SharedPreferences>((ref) { throw UnimplementedError(); });
然后我们可以在 ProviderScope 组件中进行依赖覆盖
1 2 3 4 5 6 7 8 9 10 11
Future<void> main() async { WidgetsFlutterBinding.ensureInitialized(); final sharedPreferences = await SharedPreferences.getInstance(); runApp(ProviderScope( overrides: [ // override the previous value with the new object sharedPreferencesProvider.overrideWithValue(sharedPreferences), ], child: MyApp(), )); }
dependencies: # or flutter_riverpod/hooks_riverpod as per https://riverpod.dev/docs/getting_started riverpod:^2.4.10 # the annotation package containing @riverpod riverpod_annotation:^2.3.4 dev_dependencies: # a tool for running code generators build_runner: # the code generator riverpod_generator:^2.3.9 # riverpod_lint makes it easier to work with Riverpod riverpod_lint:^2.3.7 # import custom_lint too as riverpod_lint depends on it custom_lint:
其中riverpod_lint和custom_lint这两个包是可选的。 之后我们需要在watch模式下启动代码生成器 flutter pub run build_runner watch -d,较新的flutter版本会提示使用dart run build_runner watch -d。
简单使用
我们来看个简单的示例,从 Provider 开始 没有使用注解生成器之前:
1 2 3 4 5 6 7
// dio_provider.dart import'package:dio/dio.dart'; import'package:flutter_riverpod/flutter_riverpod.dart'; // a provider for the Dio client to be used by the rest of the app final dioProvider = Provider<Dio>((ref) { return Dio(); });
使用注解生成器之后
1 2 3 4 5 6 7 8 9 10 11 12
import'package:dio/dio.dart'; // 1. import the riverpod_annotation package import'package:riverpod_annotation/riverpod_annotation.dart'; // 2. add a part file part'dio_provider.g.dart';
//需要执行 flutter pub run build_runner watch -d 来生成对应代码 @riverpod Dio dio(DioRef ref){ return Dio(); }