【问题标题】:Getting StateError (Bad state: Too many elements) while streaming in Dart/Flutter在 Dart/Flutter 中流式传输时出现 StateError(错误状态:元素过多)
【发布时间】:2021-08-16 03:32:31
【问题描述】:

我正在使用 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 属性发生变化,gameState 在 setter 方法中流式传输,如:

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

我想添加新的 gameState 以根据新状态和播放器列表进行流式传输和重建某些内容。但现在我得到了

StateError (Bad state: Too many elements)

定义和抛出如下: https://api.flutter.dev/flutter/dart-async/Stream/single.html

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

尝试 { 抛出

IterableElementError.tooMany();

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

【问题讨论】:

    标签: flutter dart stream-builder dart-stream


    【解决方案1】:

    Stream.singleList.single 的异步等效项,它接受 List 并返回列表中唯一的元素:

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

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

    您没有包含实际调用 single 的代码,因此很难知道您将其用于什么目的,但一个常见的错误是认为 single 为您提供了Stream.

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

    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. 如果你想以独立于 Flutter 的方式做类似的事情,你可以使用 rxdart 包和 BehaviorSubject 类:
    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
    

    【讨论】:

    • 嗨。我没有在任何地方使用 Stream.single,不知道存在该方法。我找不到有关异常的任何线索,所以我将代码更改为使用 rxdart,注意不可变性。现在它看起来像工作,如果它再次发生,我会通知。谢谢
    猜你喜欢
    • 2022-07-01
    • 2023-01-25
    • 2021-09-19
    • 2021-01-17
    • 2022-12-14
    • 1970-01-01
    • 2022-08-20
    • 2013-08-18
    • 1970-01-01
    相关资源
    最近更新 更多