我对 Riverpod 提供商有疑问。 当我们观察提供者中另一个提供者的状态和通知者时,它们可以被自动处置,即使它是非一次性提供者。
更详细: https://github.com/rrousselGit/riverpod/issues/3592
测试代码,可以在dartpad.dev上测试 请仅关注控制台输出和 UI 上的家庭控制器 ID。计数器不工作是正常的。
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(
ProviderScope(
observers: [Logger()],
child: const MyApp(),
),
);
}
class Logger extends ProviderObserver {
@override
void didAddProvider(
ProviderBase<dynamic> provider,
Object? value,
ProviderContainer container,
) {
print('Added [${provider.name ?? provider.runtimeType}] value: $value');
}
@override
void didDisposeProvider(
ProviderBase<dynamic> provider,
ProviderContainer container,
) {
print('Disposed [${provider.name ?? provider.runtimeType}]');
}
}
class HomeControllerState {
HomeControllerState({required this.id});
final int id;
}
class HomeController extends StateNotifier<HomeControllerState> {
HomeController(this.ref)
: super(HomeControllerState(id: Random().nextInt(1000)));
late final StateNotifierProviderRef<HomeController, HomeControllerState> ref;
@override
HomeControllerState build() {
return HomeControllerState(id: Random().nextInt(1000));
}
void watch() {
ref.watch(testProvider);
}
void increment() {
ref.watch(testProvider.notifier).increment();
}
}
final homeControllerProvider =
StateNotifierProvider<HomeController, HomeControllerState>((ref) {
return HomeController(ref);
});
class TestState {
TestState({this.count = 0});
final int count;
TestState copyWith({required int count}) {
return TestState(count: count);
}
}
class TestController extends Notifier<TestState> {
@override
TestState build() {
return TestState();
}
void increment() {
state = state.copyWith(count: state.count + 1);
}
}
final testProvider =
NotifierProvider<TestController, TestState>(TestController.new);
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
colorSchemeSeed: Colors.blue,
useMaterial3: true,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends ConsumerWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final homeControllerState = ref.watch(homeControllerProvider);
final homeController = ref.watch(homeControllerProvider.notifier);
//final testState = ref.watch(testProvider);
return Scaffold(
appBar: AppBar(
title: const Text('Riverpod Example with Nested Providers'),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('HomeController ID: ${homeControllerState.id}'),
const SizedBox(height: 20),
const Text('TestController State:'),
Text(
'000',
style: Theme.of(context).textTheme.headlineMedium,
),
ElevatedButton(
onPressed: () {
homeController.watch();
},
child: Text('watch')),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => homeController.increment(),
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
现在我解决并理解了 这不是一个错误;而是一个错误。这是 Riverpod 的预期行为。
了解这一点非常重要:如果您在提供程序中调用
watch
并且监视的提供程序发生更改,则该提供程序也将被重新创建。
在这种情况下,我们应该使用
listen
。
我说得对吗?