【问题标题】:Flutter application freezes after notifyListeners在 notifyListeners 后 Flutter 应用程序冻结
【发布时间】:2020-01-10 17:31:23
【问题描述】:

我正在尝试使用 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);
// ...

如您所见,build 方法包含多个嵌套的 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 并不能解决问题。

【问题讨论】:

  • 出于好奇,你为什么使用listen: false来获取CompanyData?
  • 当我也使用Consumer 时,是否有理由将其设置为true?编辑:true
  • 啊,确实,我刚刚意识到你也使用了消费者(顺便说一句,这很奇怪。你不需要两者)
  • notifyListener 是否正确完成,还是应用程序卡在那里?
  • 我读到listen: true 调用setState 时发生变化,我认为它与StatelessWidget 不兼容

标签: flutter dart bloc


【解决方案1】:

我发布我的错误以供将来参考。我在课堂上这样做:

static Stream<Obj1> stream() async* {
    while (true) {
      yield Obj1();
    }
  }

_subscription = Obj1.stream().listen((event) {
   // do something...
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    • 2020-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多