0

我正在使用 Multiprovider 来提供我的自定义 GameLobby 类,如下所示:

var game_lobby = GameLobby(user: user);
  return MultiProvider(
    providers: [
      StreamProvider<GameState>(create: (_) => game_lobby.gameStateStream,),
      Provider<GameLobby>(create: (_) => game_lobby,),
    ],
    child: GameRoomScreen()
  );

后来,在 GameLobby 类中,我调用了 firebase.firestore 来创建一个新集合

await gameRef.doc(user.uid).set({
    'lobbyName': 'Lobimiz',
    'code' : generateNewRoomCode(),
    'date': Timestamp.now(),
    'players' : [user.uid]
  })
  .then((value) => {
    gameRef.doc(user.uid).snapshots().listen((event) {
      
      Map<String, dynamic> firestoreInfo = event.data();
      
      players = [...firestoreInfo['players']];
      print(event.data().toString());
      gameState = GameState.InLobby; /* GAMESTATE SETTER IS CALLED */

    })
  })
  // ignore: missing_return
  .onError((error, stackTrace) {print(error.toString());});

此代码通常第一次工作。当我出于测试目的在firebase上手动插入一个条目时,gameRef.doc(user.uid).snapshots().listen() 会再次触发,因为条目已更改并且我正在收听它。

这次 gameState 属性是 change 并且 gameState 在 setter 方法中流式传输,例如:

set gameState(GameState state){
    this._gameState = state;
    this._streamController.sink.add(this._gameState);
  }

我想添加新的游戏状态来根据新状态和播放器列表进行流式传输和重建。但现在我得到

StateError(坏状态:元素太多)

在这里定义和抛出: https ://api.flutter.dev/flutter/dart-async/Stream/single.html

// 这是我们得到的第二个元素。

尝试{扔

IterableElementError.tooMany();

这里有什么问题?流一次不允许多个接收器元素吗?

4

1 回答 1

0

Stream.single是 的异步等价物List.single,它接受 aList并返回列表中唯一的元素:

['hello'].single  // returns the String 'hello'
['hello', 'world'].single  // throws StateError
[].single  // also throws StateError

Stream.single行为类似:如果你在没有元素的流上调用它,它会抛出,如果你在有 2 个或更多元素的流上调用它,它也会抛出。

single您没有包含实际single调用Stream.

不幸的是, DartStream并没有真正的“当前值”。如果这是您所追求的,您有几个选择:

  1. 使用StreamBuilder
StreamBuilder(
  stream: stream,  // make sure you create this outside build(), e.g. in initState()
  builder: (context, snapshot) {
    // snapshot.data gives you the "current value"
  }
)
  1. 如果您想以独立于颤振的方式做类似的事情,您可以使用rxdart包和 tehBehaviorSubject类:
BehaviorSubject subject = streamData();  // a special type of stream provided by rxdart 
await doSomeAsyncStuff();
subject.value  // the last value added to this subject, or throws if nothing was added
于 2021-05-30T19:48:48.143 回答