我正在将我的 Flutter 应用程序从使用 Provider 包迁移到 Riverpod 进行状态管理。但是,我遇到了一个障碍,并显示以下错误消息:
“ChangeNotifierProvider”不是一个函数。尝试将名称更正为 匹配现有函数,或定义名为的方法或函数 'ChangeNotifierProvider'
在我的主应用程序文件中尝试将
Provider
替换为 Riverpod 等效项后,在编译期间出现此错误。
我的目标是利用 Riverpod 的增强功能和可扩展性。我对使用它的
ChangeNotifierProvider
来管理应用程序状态特别感兴趣。
我尝试过的:
代码示例:
void main() async {
await Hive.initFlutter();
await Hive.openBox("Habit_Database");
runApp(MultiProvider(providers: [
ChangeNotifierProvider(
create: (context) => UserProvider(),
),
], child: const MyApp()));
}
问题:如何正确地将
ChangeNotifierProvider
从Provider迁移到Riverpod,解决上述错误?任何具体示例或文档参考将不胜感激。
提前感谢您的帮助!
我现在正在为客户做这件事。我选择维护现有的提供商基础设施,同时慢慢地将一个提供商迁移到 Riverpod。
为了完成这项工作,我首先为所有导出的提供程序函数构建了一个重命名垫片。它导入提供程序,并建立 typedef 来为这些名称起别名,使其普遍以“X”结尾,包括 BlockContext 上的扩展名,该扩展名变为 .readX 和 .selectX。我对此进行了测试,一开始没有“X”,然后一次重命名 VSC 中的每个符号,结果出人意料地效果很好。重命名垫片看起来像:
import 'package:provider/provider.dart' as provider;
typedef ProviderX<T> = provider.Provider<T>;
typedef MultiProviderX = provider.MultiProvider;
typedef ChangeNotifierProviderX<T extends ChangeNotifier> = provider.ChangeNotifierProvider<T>;
持续约 100 行。棘手的是扩展:
extension ReadContext on BuildContext {
T readX<T>() => provider.ReadContext(this).read<T>();
}
extension SelectContext on BuildContext {
R selectX<T, R>(R Function(T value) selector) => provider.SelectContext(this).select(selector);
}
不可否认,一旦我开始使用该模式,Github 副驾驶就热切地向我提供了一行又一行的内容,并且最初只在一些事情上出错了。
接下来,我将 RiverPod ProviderScope 添加到我的 runApp 中,并选择要迁移的特定提供程序。我在 RiverPod 中创建了等效项,很好地命名了,因为“FooProvider”变成了“fooProvider”,然后在 .readX 或 ConsumerX 访问中找到对该类的所有引用。我插入了与 Consumer 块或 ConsumerWidget 小部件等效的内容,为我提供了一个参考,以便根据需要与 ref.read 或 ref.watch 一起使用。
这不是小事。但是一旦你克服了“伟大的重命名”障碍,剩下的就只是相当机械的翻译,并且可以逐步完成。
错误消息表明
ChangeNotifierProvider
不是函数。您正在尝试从 provider
迁移到 Riverpod.
在 Riverpod 中,
ChangeNotifierProvider
的等效类是 ChangeNotifierProvider.autoDispose.
所以你应该替换这一行:
ChangeNotifierProvider(
create: (context) =>
UserProvider(),
),
用这一行:
ChangeNotifierProvider.autoDispose( create: (context) => UserProvider(),),
这应该可以解决问题。