【问题标题】:Why should didUpdateWidget be implemented for subscriptions and ChangeNotifiers?为什么要为订阅和 ChangeNotifier 实现 didUpdateWidget?
【发布时间】:2020-03-22 23:00:26
【问题描述】:

我创建了一个自定义小部件,它监听 ChangeNotifier 并在通知程序触发时调用提供的回调。这用于在通知器更改时执行一次性任务,例如导航。

一切似乎都很好,但我偶然发现了documentation of didUpdateWidget,上面写着:

如果 State 的 build 方法依赖于一个自身可以改变状态的对象,例如 ChangeNotifier 或 Stream,或者其他可以订阅接收通知的对象,那么请确保在 initState、didUpdateWidget 中正确订阅和取消订阅,并处理:

  • 在 initState 中,订阅对象。
  • 如果更新的小部件配置需要替换对象,则在 didUpdateWidget 中取消订阅旧对象并订阅新对象。
  • 在 dispose 中,取消订阅对象。

出于显而易见的原因,我正在处理第一点和最后一点,但有人可以解释为什么我还必须实施 didUpdateWidget 吗?如果我不这样做会出什么问题?

额外问题:我还没有在我的应用程序中使用提供程序。它是否提供了开箱即用的类似功能?我找不到这样的东西。

我的小部件代码:

class ChangeNotifierListener<T extends ChangeNotifier> extends StatefulWidget {
  final Widget child;
  final T changeNotifier;
  final void Function(T changeNotifier) onChanged;

  ChangeNotifierListener(
      {@required this.child,
      @required this.changeNotifier,
      @required this.onChanged});

  @override
  _ChangeNotifierListenerState createState() =>
      _ChangeNotifierListenerState<T>();
}

class _ChangeNotifierListenerState<T extends ChangeNotifier>
    extends State<ChangeNotifierListener<T>> {
  VoidCallback _callback;

  @override
  Widget build(BuildContext context) => widget.child;

  @override
  void initState() {
    super.initState();
    _callback = () {
      widget.onChanged(widget.changeNotifier);
    };
    widget.changeNotifier.addListener(_callback);
  }

  @override
  void dispose() {
    widget.changeNotifier.removeListener(_callback);
    super.dispose();
  }
}

【问题讨论】:

    标签: flutter provider


    【解决方案1】:

    这部分文档是关于使用不同参数重建小部件的可行性。

    例如,使用StreamBuilder,第一次构建可能类似于:

    StreamBuilder(
      stream: Stream.value(42),
      builder: ...
    )
    

    然后发生了一些变化,StreamBuilder 被重建为:

    StreamBuilder(
      stream: Stream.value(21),
      builder: ...
    )
    

    在这种情况下,stream 发生了变化。因此,StreamBuilder 需要停止收听以前的Stream 并收听新的。

    这将通过以下didUpdateWidget 来完成:

    StreamSubscription<T> subscription;
    
    @override
    void didUpdateWidget(StreamBuilder<T> oldWidget) {
      super.didUpdateWidget(oldWidget);
      if (widget.stream != oldWidget.stream) {
        subscription?.cancel();
        subscription = widget.stream?.listen(...);
      }
    }
    

    同样的逻辑适用于ChangeNotifier 和任何其他可观察对象。

    【讨论】:

    • 谢谢,这让我明白了。基本上在我的实现中,changeNotifier 可能会发生变化,因此我应该从旧的监听器中删除监听器并将其附加到新的监听器,以防止来自旧通知器而不是新通知器的事件被传递。
    • 提供者是否附带了我在最初帖子中描述的小部件,即不根据更改重建的小部件,只是触发回调?只是为了确保我不会重新发明轮子。
    • 没有。但那个小部件基本上是AnimatedBuilder
    猜你喜欢
    • 1970-01-01
    • 2016-11-13
    • 2017-06-22
    • 2019-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 2021-06-09
    相关资源
    最近更新 更多