当 Flutter 中的全局变量更改(异步)时更新小部件

Zau*_*lov 3 dart flutter

我对 Flutter 还很陌生,我发现自己陷入了自己挖的坑中。

我想要完成的事情很简单。我有一个全局变量。让我们说var PlayerPointsToAdd。然后我有这个有状态的小部件,它应该在每次这个全局变量不为零时自动更新。我希望能够addPointsToPlayer()从另一个小部件调用。

到目前为止,我对有状态小部件的理解结束于setState((){})我只能在有状态小部件本身内部调用。

下面的代码位于有状态小部件内的容器内。每当按下此按钮时,它都会根据PlayerScoreBoard.add()返回的新列表调用 setState 。

...
child: RaisedButton(
                        onPressed: () {
                          setState(() {
                            if (PointsToAddPlayer != 0) {
                              for (int i = 0; i < PointsToAddPlayer; i++) {
                                PlayerScoreBoard.add(new Icon(
                                    Icons.check_circle_outline,
                                    size: 11));
                              }
                              PointsToAddPlayer = 0;
                            }
Run Code Online (Sandbox Code Playgroud)

我一直在阅读文档并在 YouTube 上观看 Flutter 视频,所以请不要忽略这个问题。我真的很难理解这一点。

我想我必须使用 Streams 来做到这一点。它们看起来有点复杂,但如果这是唯一的方法,我会使用它们。这是否意味着我应该创建一个全局变量,最好是一个包含变量的类,并使它的变量流到每个其他需要在变量更新时更新的小部件。因此,此 ScoreBoard 小部件必须侦听来自全局类的 Stream 并更新自身。这是否允许我更改全局类中的变量并自动将相应的小部件更新为其新状态?这是否意味着每个依赖于自身外部变量的小部件都必须监听流?我非常感谢 ELI5 来处理 Stateful Widgets 和 Streams 之间的关系。

并且因为这个全局数据会一次又一次地更新很多次,所以使用 Future 是不可能的。

非常感谢。

我错说了一个全局类变量。我的意思是说像 Map 这样的东西,在那里我可以有像gameData.PlayerPoints, 或gameData.turn.

Owc*_*zar 6

您可以尝试ValueListenableBuilder

import 'package:flutter/material.dart';

final playerPointsToAdd =
    ValueNotifier<int>(0); //TODO 1st: ValueNotifier declaration

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

class TestApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(
        routes: {
          '/': (context) => HomePage(),
        },
      );
}

//TODO you can use StatelessWidget either
class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) => Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              RaisedButton(
                // TODO 3rd: change the value
                onPressed: () => playerPointsToAdd.value++,
                child: Text('Increase'),
              ),
              ValueListenableBuilder(
                //TODO 2nd: listen playerPointsToAdd
                valueListenable: playerPointsToAdd,
                builder: (context, value, widget) {
                  //TODO here you can setState or whatever you need
                  return Text(
                      //TODO e.g.: create condition with playerPointsToAdd's value
                      value == 0
                          ? 'playerPointsToAdd equals 0 right now'
                          : value.toString());
                },
              ),
              RaisedButton(
                onPressed: () => playerPointsToAdd.value--,
                child: Text('Decrease'),
              ),
            ],
          ),
        ),
      );
}


Run Code Online (Sandbox Code Playgroud)