在notifyListeners之后Flutter应用程序冻结

时间:2019-09-08 20:57:26

标签: flutter dart bloc

我正在尝试使用Google Maps插件编写一个简单的Flutter应用。我需要使用多个BLoC / ChangeNotifier对象来管理屏幕上显示的对象。

当我在ChangeNotifier上调用notifyListeners()时,问题就出现了。调用notifyListeners()的方法完成其执行,然后应用完全冻结(没有小部件更新,无法与现有小部件进行交互)。

我试图了解问题出在哪里:我唯一了解的是CompaniesData(这是引起问题的ChangeNotifier)为空时,它可以正常工作。

class CompaniesData extends ChangeNotifier {
  Map<MarkerId, Company> _companiesMap;

  set companies(Set<Company> companies) {
    _companiesMap = companies != null
        ? Map.fromIterable(
            companies,
            key: (company) => MarkerId(company.id.toString()),
            value: (company) => company,
          )
        : null;
    notifyListeners();
    ;
  }

  bool get available => _companiesMap != null;

  Company companyWithId(MarkerId id) => available ? _companiesMap[id] : null;

  Map<MarkerId, Company> get companiesIfAvailable =>
      available ? _companiesMap : Map();

  Iterable<Company> companiesFromIds(BuildContext context, Set<int> ids) {
    Set<int> idsCopy = Set.from(ids);
    return companiesIfAvailable.entries
        .where((entry) => idsCopy.remove(entry.value.id))
        .map<Company>((entry) => entry.value);
  }
}
@override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Consumer<CompaniesData>(
          builder: (context, data, child) {
            return BlocBuilder(
              bloc: BlocProvider.of<ShownCompaniesBloc>(context),
              builder: (context, shownCompaniesState) {
                return BlocBuilder(
                  bloc: BlocProvider.of<FavoriteCompaniesBloc>(context),
                  builder: (context, favoriteCompaniesState) {
                    return BlocBuilder(
                      bloc: BlocProvider.of<MapPropertiesBloc>(context),
                      builder: (context, mapPropertiesState) {
                        CompaniesData data =
                            Provider.of<CompaniesData>(context, listen: false);
// ...

如您所见,构建方法包含多个嵌套的BLoC / Consumer对象。

@override
  void initState() {
    _fetchCompanies();
    super.initState();
  }

  void _fetchCompanies() {
    findUser().then((location) {
      Set<Company> companies = Set.from([Company.fake()]);
      // CompaniesData.companies is a setter, which calls
      // notifyListeners
      _companiesData.companies = companies;
    });
  }

我没有收到错误消息,异常,给findUser().then()的回调执行结束后,我的应用程序就死了。

编辑:

我稍微更改了代码,发现问题不是notifyListeners(或者至少不是现在)。

final Completer<Map<MarkerId, Company>> _companiesData = Completer();

_AeroMainViewState() {
    findUser()
        .then(_fetchCompanies)
        .then((companies) => _companiesData.complete(Map.fromIterable(
              companies,
              key: (company) => MarkerId(company.id.toString()),
              value: (company) => company,
            )));
  }

  Future<Set<Company>> _fetchCompanies(LatLng location) async =>
      Set.from([Company.fake()]);
// ...
child: FutureBuilder<Map<MarkerId, Company>>(
          future: _companiesData.future,
          builder: (context, snapshot) {
            // this builder function isn't called at all
            // when the Completer _companiesData is completed
            if (snapshot.connectionState == ConnectionState.done) {
              return Provider<Map<MarkerId, Company>>.value(
                  value: snapshot.data,
                  child: // ...
            } else {
              return Center(child: CircularProgressIndicator());
            }
          }),
// ...

删除ChangeNotifier不能解决问题。

1 个答案:

答案 0 :(得分:0)

我将我的错误发布给以后参考。我在上课时是这样做的:

action(s)

由于Stream可能包含无限多个对象,因此对该流的订阅阻塞了主线程(也是唯一线程)。