flutter - Flutter - 如何使用 ChangeNotifier 正确获取数据
问题描述
我想在应用程序运行后获取有关整个应用程序的天气统计数据。
我的ChangeNotifier
:
class WeatherStatsNotifier extends ChangeNotifier {
WeatherService weatherService;
Future<WeatherStats> _stats;
WeatherStatsNotifier({this.weatherService});
Future<WeatherStats> get stats => _stats;
void refreshStats() {
_stats = weatherService.fetchWeatherStats();
notifyListeners(); // it works when I remove this line
}
}
我的主文件:
final WeatherService weatherService = new WeatherService();
void main() => runApp(ChangeNotifierProvider(
create: (context) => WeatherStatsNotifier(weatherService: weatherService),
child: App()));
class App extends StatefulWidget {
@override
_AppState createState() => _AppState();
}
class _AppState extends State<App> {
@override
void didChangeDependencies() {
Provider.of<WeatherStatsNotifier>(context, listen: false).refreshStats();
super.didChangeDependencies();
}
//... build method
}
在更深的地方:
@override
Widget build(BuildContext context) {
return Consumer<WeatherStatsNotifier>(
builder: (context, value, child) {
return FutureBuilder<WeatherStats>(
future: value.stats,
builder: (context, snapshot) {
return _buildForSnapshot(snapshot);
},
);
},
);
}
最后我得到一个错误:
======== Exception caught by widgets library =======================================================
The following assertion was thrown building ChangeNotifierProvider<WeatherStatsNotifier>(message: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 4195 pos 12: '!_dirty': is not true.\nSee also: https://flutter.dev/docs/testing/errors, dirty, renderObject: RenderErrorBox#c84e8 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE DETACHED):
'package:flutter/src/widgets/framework.dart': Failed assertion: line 4195 pos 12: '!_dirty': is not true.
如何以正确的方式做到这一点?我可以在context
里面initState
使用didChangeDependencies
吗?
解决方案
当依赖关系发生变化时,即didChangeDependencies
调用 WeatherStatsNotifier。小部件已经被认为是脏的并且正在构建(可以有多个侦听器)。
但是,您正在同步refreshStats
通知侦听器,这意味着应该再次构建侦听器,但它们已经在构建。这可能会导致框架不一致,这就是为什么它是一个错误。这也是为什么删除它是“解决”问题的原因。notifyListeners();
修复它的方法是通过addPostFrameCallback
或异步执行更改Future.microtask
。
@override
void didChangeDependencies() {
super.didChangeDependencies();
Future.microtask(() {
Provider.of<WeatherStatsNotifier>(context, listen: false).refreshStats();
});
}
请注意,如果您有多个依赖项,您可能应该检查实例是否在didChangeDependencies
.
推荐阅读
- fortran - 如何在 Fortran 中制作通用过程指针?
- javascript - 使用 fetch 上传图片,我得到 200 状态,但图片没有上传
- kubernetes - Helm 管理服务集合
- java - 来自 String 的 Java AST 表单注释
- ruby-on-rails - 销毁后重定向到'category_products_path'不起作用(:未给出category_id)
- amazon-web-services - Amazon S3 AWS 的定价结构
- vue.js - Vue cli 3 postcss显示:flex问题
- java - 使用三个小数点格式化输出
- sql - SQL删除特定列中与另一行具有相同值的重复行
- javascript - 仅在输入输入时运行 onclick 事件