首页 > 解决方案 > 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吗?

标签: flutterdartflutter-provider

解决方案


当依赖关系发生变化时,即didChangeDependencies调用 Wea​​therStatsNotifier。小部件已经被认为是脏的并且正在构建(可以有多个侦听器)。

但是,您正在同步refreshStats通知侦听器,这意味着应该再次构建侦听器,但它们已经在构建。这可能会导致框架不一致,这就是为什么它是一个错误。这也是为什么删除它是“解决”问题的原因。notifyListeners();

修复它的方法是通过addPostFrameCallback或异步执行更改Future.microtask

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();

    Future.microtask(() {
      Provider.of<WeatherStatsNotifier>(context, listen: false).refreshStats();
    });

  }

请注意,如果您有多个依赖项,您可能应该检查实例是否在didChangeDependencies.


推荐阅读