如何使用 Flutter 在恢复状态下重建 StreamBuilder

How to rebuild StreamBuilder on resumed state with Flutter

我使用 BLoC 模式开发了一个应用程序。 在我的应用程序中有 2 条路线,路线 A 和路线 B,它们都访问相同的数据。 如下移动路线时出现的问题。

  1. 从显示数据的路线 A 移动到路线 B。
  2. 更新路由B的数据。
  3. 回到路线A。

回到路线A后,显示数据的StreamBuilder不再自动更新。 如何让 StreamBuilder 更新恢复状态?

这里是示例代码。

routeA.dart

class RouteA extends StatefulWidget {
  @override
  _RouteAState createState() => _RouteAState();
}

class _RouteAState extends State<RouteA> {
  @override
  Widget build(BuildContext context) {
    final bloc = Bloc();
    return Column(
      children: [
        StreamBuilder(    // this StreamBuilder never updates on resumed state
            stream: bloc.data, // mistake, fixed. before: bloc.count
            builder: (_, snapshot) => Text(
                  snapshot.data ?? "",
                )),
        RaisedButton(
          child: Text("Move to route B"),
          onPressed: () {
            Navigator.of(context).pushNamed("routeB");
          },
        ),
      ],
    );
  }
}

routeB.dart

class RouteB extends StatefulWidget {
  @override
  _RouteBState createState() => _RouteBState();
}

class _RouteBState extends State<RouteB> {
  @override
  Widget build(BuildContext context) {
    final bloc = Bloc();
    return Center(
      child: RaisedButton(
        child: Text("Update data"),
        onPressed: () {
          bloc.update.add(null);
        },
      ),
    );
  }
}

bloc.dart

class Bloc {
  Stream<String> data;
  Sink<void> update;
  Model _model;
  
  Bloc() {
    _model = Model();
    
    final update = PublishSubject<void>();
    this.update = update;
    
    final data = BehaviorSubject<String>(seedValue: "");
    this.data = data;
    
    update.map((event) => _model.update()).listen((event) => data.sink.add(_model.getData()));
  }
}

model.dart

class Model {
  static Model _model;

  factory Model() {    // model is singleton.
    _model ??= Model._();
    return _model;
  }

  Model._();

  int _data = 0;

  void update() {
    _data++;
  }

  String getData() {
    return _data.toString();
  }
}

StreamBuilder 在数据发生变化时更新数据,而不是仅通过调用 stream

路线A

class RouteA extends StatefulWidget {
  @override
  _RouteAState createState() => _RouteAState();
}

class _RouteAState extends State<RouteA> {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        StreamBuilder(    // this StreamBuilder never updates on resumed state
            stream: bloc.data, // mistake, fixed. before: bloc.count
            builder: (_, snapshot) => Text(
              snapshot.data ?? "",
            )),
        RaisedButton(
          child: Text("Move to route B"),
          onPressed: () {
            Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
              return RouteB();
            }));
          },
        ),
      ],
    );
  }
}

路线B

class RouteB extends StatefulWidget {
  @override
  _RouteBState createState() => _RouteBState();
}

class _RouteBState extends State<RouteB> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: RaisedButton(
        child: Text("Update data"),
        onPressed: () {
          bloc.updateData();
        },
      ),
    );
  }
}

集团

class Bloc {
  final _update = PublishSubject<String>();
  Model _model = Model();
  Stream<String> get data => _update.stream;

  void updateData() async {
    _model.update();
    _update.sink.add(_model.getData());

    _update.stream.listen((event) {
      print(event);
    });
  }

  dispose() {
    _update.close();
  }
}

final bloc = Bloc();

只需按照上述更改,它就会为您解决问题。