StreamBuilder не корректно обновляет новое значение - PullRequest
0 голосов
/ 30 мая 2019

Возможно, это моя ошибка или глупая ошибка, но это то, что происходит со мной:

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.дротик:

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 голосов
/ 30 мая 2019

С Framework.dart:

A StatelessWidget строит себя в зависимости от данных, которые имеют два условия:

  1. может читаться синхронно, когда виджет встроенный. И:
  2. может измениться за время существования виджета.

Вот почему, когда вы делаете Login2 как StatelessWidget, а затем изменяете данные в authController синхронно, это немедленно отражается, потому что оно удовлетворяет обоим условиям. Но когда вы используете async функцию внутри onTap(), вы ломаете первую.

И почему StatefulWidget работает с функцией async, потому что ее функции build требуется только изменение данных для неявного запуска setState() независимо от того, доступна ли эта информация синхронно или асинхронно.

...