Flutter:在StatelessWidget中添加侦听器的位置?

foo*_*ist 14 listener dart flutter statelesswidget

如果我使用的是StatefulWidget,那么我将在initState方法中监听流。在StatelessWidget中,我该在哪里做类似的事情(想将Bloc与流一起用于状态管理)?我可以在build方法中做到这一点,但由于这些都是重复性的,所以我想知道是否有比检查如下所示的现有侦听器更有效的方法。我知道这是一个多余且无用的示例,但这只是为了显示问题。

    import "package:rxdart/rxdart.dart";

    import 'package:flutter/material.dart';

    final counter = BehaviorSubject<int>();
    final notifier = ValueNotifier<int>(0);

    void main() => runApp(MyApp());

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        if (!counter.hasListener)
          counter.listen((value) => notifier.value += value);  

        return MaterialApp(
          home: Scaffold(
            body: Center(
              child:FlatButton(
                onPressed: () => counter.add(1),
                child: ValueListenableBuilder(
                  valueListenable: notifier,
                  builder: (context, value, child) => Text(
                    value.toString()
                  ),
                ),
              )
            ),
          )
        );
      }
    }
Run Code Online (Sandbox Code Playgroud)

Rém*_*let 11

没有一种干净的方法可以让 StatelessWidget 监听一个 Listenable/Stream。您将始终需要一个 StatefulWidget。

另一方面,您可以使用组合来编写 StatefulWidget 一次,然后就完成了。

该图案常见的例子是小部件,例如ValueListenableBuilderStreamBuilder,或AnimatedBuilder。但也有可能做同样的事情,听也是。

你会这样使用它:

class Foo extends StatelessWidget {
  Foo({Key key, this.counter}): super(key: key);

  final ValueListenable<int> counter;

  @override
  Widget build(BuildContext context) {
    return ValueListenableListener(
      valueListenable: counter,
      onChange: (value) {
        // TODO: do something
      },
      child: Something(),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

哪里ValueListenableListener是这样实现的:

class ValueListenableListener<T> extends StatefulWidget {
  const ValueListenableListener(
      {Key key, this.valueListenable, this.onChange, this.child})
      : super(key: key);

  final ValueListenable<T> valueListenable;
  final ValueChanged<T> onChange;
  final Widget child;

  @override
  _ValueListenableListenerState createState() =>
      _ValueListenableListenerState();
}

class _ValueListenableListenerState extends State<ValueListenableListener> {
  @override
  void initState() {
    super.initState();
    widget.valueListenable?.addListener(_listener);
    _listener();
  }

  @override
  void didUpdateWidget(ValueListenableListener oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.valueListenable != widget.valueListenable) {
      oldWidget.valueListenable?.removeListener(_listener);
      widget.valueListenable?.addListener(_listener);
      _listener();
    }
  }

  @override
  void dispose() {
    widget.valueListenable?.removeListener(_listener);
    super.dispose();
  }

  void _listener() {
    widget.onChange?.call(widget.valueListenable.value);
  }

  @override
  Widget build(BuildContext context) {
    return widget.child;
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 很高兴看到一位颤振霸主加入讨论。一如既往,非常感谢您提供的重要信息! (3认同)

Wil*_*lly 9

你不应该 不处理可能会修改其值的变量是无状态小部件的目的:

无状态小部件永远不会改变。

更新:我认为这是理解Flutter的状态管理概念的问题。Flutter小组推荐的这种新方法应该消除一些混乱。

  • 谢谢您的回答。在 StatelessWidgets 中使用 StreamBuilders 有什么问题?我知道“无状态”小部件应该不会改变其状态,但是这样您编写的代码更少,避免了 StatefulWidgets。我看不出这会如何导致问题,而且我已经看到很多人这样做了。 (2认同)