[Flutter]:notifyListeners 在其他屏幕或弹出窗口中不起作用

[Flutter]: notifyListeners not working from other screens or popups

我正在使用提供程序库进行状态管理,到目前为止一切正常。但是,我注意到当从另一个屏幕(或 showModalBottomSheet 之类的弹出窗口)调用 notifyListeners 时,我的 UI 不会收到通知。

我在 provider 中使用的方法看起来像这样,并将一个项目添加到 ListView:

void addEntry(http.Response response) {
  Group group = Group.fromJson(jsonDecode(response.body));
  groups.add(group);
  notifyListeners();
}

至于 UI 整个屏幕被包裹在 Consumer 中。从屏幕中的按钮调用此方法工作正常并且列表已更新。从使用 showModalBottomSheet 创建的弹出窗口调用此方法不会更新 UI.

如何确保 UI 收到更改通知?


更新 #1:

我有一个像这样调用 showModalBottomSheet 的按钮:

showModalBottomSheet<void>(
  ...
  context: context,
  builder: (context) {
    return Padding(
      padding: MediaQuery.of(context).viewInsets,
      child: AddWidget(model: Provider.of<GroupsProvider>(context)),
    );
  },
);

所以它创建了一个带有单独小部件的弹出窗口。当按下另一个按钮时,该单独的小部件依次执行此操作:

widget.model.createGroup(name, icon);

这个方法最终会调用addEntry。正如我所说,这在没有弹出窗口的情况下工作得很好,但在弹出窗口中根本不起作用:/

Pop-ups 之类的 bottomsheets 很可能是从根导航器打开的,因此提供了不同的上下文,如果您的提供者不是在根导航器之上创建的,即在 MaterialApp 之上,则会导致此问题。 来自 showModalBottomSheetbuildercontext 不是创建提供者的地方。 我能想到两种解决方案:

  1. 就在调用 showModalBottomSheet 之前,您可以创建对 Provider 的引用,然后将其传递给 AddWidget。
var provider = Provider.of<GroupsProvider>(context, listen:false);

showModalBottomSheet<void>(
  ...
  context: context,
  builder: (context) {
    return Padding(
      padding: MediaQuery.of(context).viewInsets,
      child: AddWidget(model: provider),
    );
  },
);

  1. 使用 ChangeNotifierProvider.value 并将小部件包装在构建器中。
showModalBottomSheet<void>(
  ...
  context: context,
  builder: (_) {
    return ChangeNotifierProvider.value(
          value: Provider.of<GroupsProvider>(context, listen:false),
         builder: (context, _) =>
                Padding(
      padding: MediaQuery.of(context).viewInsets,
      child: AddWidget(model: Provider.of<GroupsProvider>(context)),
    );
       );
  },
);

(2) 确保它下面的小部件树可以访问同一个 Provider 实例。对于新屏幕,您可以这样做:

Navigator.push(
  context,
  MaterialPageRoute(
   builder: (_) => ChangeNotifierProvider.value(...),
   ),
);

在调试模式下查看小部件检查器将帮助您更好地理解