StreamBuilder无法正确刷新新值

时间:2019-05-30 12:09:14

标签: flutter dart rxdart

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

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!");
                        },
                      );
                    }
                  ),
  ))));}}

一切顺利。 但是,如果我使用async添加异步函数并在authController.updateHometown之前等待:

Login_screen.dart:

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

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

但是如果我使用statefulWidget类:

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 为什么会这样?

1 个答案:

答案 0 :(得分:0)

来自Framework.dart

WebView根据具有两个条件的数据进行构建:

    可以在窗口小部件处于同步状态时读取
  1. 内置的。和:
  2. 在窗口小部件的生存期内可能会发生变化。

这就是为什么当将StatelessWidget设置为Login2,然后同步更改StatelessWidget中的数据时,会立即反映出来,因为它同时满足这两个条件。但是,当您在authController中使用async函数时,则会破坏第一个函数。

onTap()StatefulWidget函数一起使用的原因是,其async函数仅需要更改数据即可隐式触发build,而不管此信息是同步还是异步可用