StreamBuilder 未正确刷新新值

StreamBuilder not correctly refreshing on new value

可能是我的错或一个愚蠢的错误,但这就是发生在我身上的事情:

authController.dart:

class AuthController {
BehaviorSubject _hometownController = BehaviorSubject();
Observable get hometown => _hometownController.stream;
void updateHometown(String hometown) {
    _hometownController.add(hometown);
    print(_hometownController.value); <- This always prints the expected value: "Hello!"`
}
}

Login_screen.dart:

class Login2 extends StatelessWidget {
  AuthController authController = new AuthController();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Builder(
        builder: (BuildContext context) =>
          Container(
            padding: EdgeInsets.all(32.0),
            child: Center(
              child:
                  //Hometown:
                  StreamBuilder(
                    stream: authController.hometown,
                    builder: (BuildContext context, AsyncSnapshot snap) {
                      return ListTile(
                        leading: Icon(Icons.map),
                        title: Text("Hometown:"),
                        subtitle: snap.hasData ? Text(snap.data) : Text("Not set"),
                        onTap: () {
                          authController.updateHometown("Hello!");
                        },
                      );
                    }
                  ),
  ))));}}

一切顺利。 但是如果我在 authController.updateHometown:

之前添加一个带有 async 和 await 的异步函数

Login_screen.dart:

                            onTap: () async {
                              var x = await something(); <- This always successfully completes
                              authController.updateHometown("Hello!");
                            },

流永远不会收到新值,StreamBuilder 也永远不会重建!

但是如果我使用 statefulWidget class:

class Login2 extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => Login2State();
}

class Login2State extends State<Login2> {
  AuthController authController;

  @override
  void initState() {
    authController = new AuthController();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Builder(
        builder: (BuildContext context) =>
          Container(
            padding: EdgeInsets.all(32.0),
            child: Center(
              child:
                  //Hometown:
                  StreamBuilder(
                    stream: authController.hometown,
                    builder: (BuildContext context, AsyncSnapshot snap) {
                      return ListTile(
                        leading: Icon(Icons.map),
                        title: Text("Hometown:"),
                        subtitle: snap.hasData ? Text(snap.data) : Text("Not set"),
                        onTap: () async {
                          var x = await something();
                          authController.updateHometown("Hello!");
                        },
                      );
     }),))));}}

一切顺利,即使我从不调用 setState 为什么会这样?

来自 Framework.dart :

A StatelessWidget 根据具有两个条件的数据构建自身:

  1. widget时可以同步读取 建成。并且:
  2. 可能会在小部件的生命周期内发生变化。

这就是为什么当你把Login2做成StatelessWidget,然后同步改变authController中的数据时,它会立即反映出来,因为它同时满足这两个条件。但是当你在 onTap() 中使用 async 函数时,你破坏了第一个。

为什么 StatefulWidgetasync 函数一起工作是因为它的 build 函数只需要一个数据更改就可以隐式触发 setState() 而不管这个信息是否同步可用或异步。