我尝试升级我的 Flutter 应用程序以供Provider 4.0.1今天使用,但以下代码在将值分配为 null 时崩溃。
这是我试图转换的代码。我只改SingleChildCloneableWidget到SingleChildStatelessWidget其编译OK。
import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.dart';
List<SingleChildStatelessWidget> providers = [
...independentServices,
...dependentServices,
...uiConsumableProviders
];
List<SingleChildStatelessWidget> independentServices = [
Provider.value(value: Api()),
Provider.value(value: Tbl()),
Provider.value(value: Bill()),
Provider.value(value: Sale()),
Provider.value(value: Category()),
Provider.value(value: Menu()),
];
List<SingleChildStatelessWidget> dependentServices = [
ProxyProvider<Api, AuthenticationService>(
update: (context, api, authenticationService) => AuthenticationService(api: api),
),
];
List<SingleChildStatelessWidget> uiConsumableProviders = [
StreamProvider<User>(
create: (context) => Provider.of<AuthenticationService>(context, listen: false).user,
),
lazy: false
];
Run Code Online (Sandbox Code Playgroud)
我是这样实现的:
StreamController<User> _userController = StreamController<User>();
Stream<User> get user => _userController.stream;
Run Code Online (Sandbox Code Playgroud)
崩溃发生在这一行:
Future<void> _setFixedLanguageStrings(BuildContext context) async {
User _user = Provider.of<User>(context);
_user.homeString = await translate(context, 'Home');
Run Code Online (Sandbox Code Playgroud)
在 null 上调用了 getter 'language'。接收器:空
这很好用,Provider 3.0.3但显然我需要做更多。
我的原始代码来自 本教程。
编辑:我通过添加lazy: false流提供程序创建方法解决了该问题,但随后在此代码中出现了另一个错误。
Future<String> translate(BuildContext context, _term) async {
final String _languageCode = Provider.of<User>(context).language;
Run Code Online (Sandbox Code Playgroud)
产生了这个错误:
发生异常。_AssertionError ('package:provider/src/provider.dart': Failed assertion: line 213 pos 7: 'context.owner.debugBuilding || listen == false || _debugIsInInheritedProviderUpdate': 试图监听提供者公开的值,来自在小部件树之外。
这可能是由调用 Provider.of 而不传递 的事件处理程序(如按钮的 onPressed)引起的
listen: false。要修复,请编写:Provider.of(context, listen: false);
它不受支持,因为当小部件树不关心该值时,可能会毫无意义地重建与事件处理程序关联的小部件。)
我添加listen: false到上面似乎解决了该问题的行,但是我尝试使用的下一个提供程序产生了此错误:
试图从小部件树外部监听提供者公开的值。
这可能是由调用 Provider.of 而不传递 的事件处理程序(如按钮的 onPressed)引起的
listen: false。要修复,请编写:Provider.of(context, listen: false);
它不受支持,因为当小部件树不关心该值时,可能会毫无意义地重建与事件处理程序关联的小部件。'package:provider/src/provider.dart':断言失败:第 213 行位置 7:'context.owner.debugBuilding || 听 == 假 || _debugIsInInheritedProviderUpdate'
我现在应该去调用提供者的每个实例并添加listen: false吗?我需要有人解释发生了什么变化以及原因,因为我在 Flutter 还是个新手,而且Provider. 有很多次我在我的代码中调用 Provider 并且最后一个错误没有返回代码位置。
是listen: false现在总是在它之前是不是需要或有我错过了什么东西?我开始在每次调用时添加 listen: false 以实例化 Provider 变量,它似乎正在工作,但这是正确的方法吗?我应该添加listen: false到每个电话Provider.of并称之为一天吗?
编辑:每当从窗口小部件树的可见部分之外调用提供程序时,就会出现错误。这种区别很重要。
在onPressed、OnTap、onLongPressed等事件处理程序上,我们必须使用
Provider.of<T>(context,listen:false)
Run Code Online (Sandbox Code Playgroud)
原因是他们不会监听任何更新更改,而是负责进行更改。
而像 Text 等小部件负责显示......因此需要在每次更改时更新......因此使用
Provider.of<T>(context,listen:true) //by default is listen:true
Run Code Online (Sandbox Code Playgroud)
小智 7
listen:true成为默认值是合乎逻辑的。
它没有在事件处理程序中指定不合逻辑的内容。listen: false
此外,4.1.0 将以某种方式提供比 Provider.of 更短的替代方案:
context.read<T>() // Provider.of<T>(context, listen: false)
context.watch<T>() // Provider.of<T>(context)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9959 次 |
| 最近记录: |