I want to display a chessboard with data synchronized with Firestore in real time. After creating a room document on Firestore, I pulled data from that document to the app and used StreamBuilder to display it. But a very confusing error appears:

The following _TypeError was thrown building StreamBuilder<DocumentSnapshot<Map<String, dynamic>>>(dirty, state: _StreamBuilderBaseState<DocumentSnapshot<Map<String, dynamic>>, AsyncSnapshot<DocumentSnapshot<Map<String, dynamic>>>>#954da):

type 'List' is not a subtype of type 'List<Map<String, dynamic>>' in type cast

Here’s the code:

Stream<DocumentSnapshot<Map<String, dynamic>>> watchRoom(String roomId) {  
  return FirebaseFirestore.instance.collection("rooms").doc(roomId).snapshots();  
}
class OnlineBoardWidget extends StatelessWidget {  
  const OnlineBoardWidget({super.key});  
  
  @override  
  Widget build(BuildContext context) {  
    final columnCount = OnlineGameController.to.room.board.columnCount;  
    final rowCount = OnlineGameController.to.room.board.rowCount;  
    logger.t('build online board ($rowCount, $columnCount)');  
  
    return StreamBuilder(  
    // theo dõi một room document trên firestore
      stream: firestoreService.watchRoom("ec483c14-f414-44ae-bea1-b84e409331f0"),  
        builder: (context, snapshot) {  
          if (snapshot.connectionState == ConnectionState.waiting) {  
            return CircularProgressIndicator();  
          } else if (snapshot.hasError) {  
            return Text('Error: ${snapshot.error}');  
          } else {  
            Map<String, dynamic> json = snapshot.data!.data()!;  
            logger.i(json);  // json data is logged
            OnlineRoom room = OnlineRoom.fromJson(json);  // ERROR apears here
            logger.i(room);  
            return Text(room.toString(), style: kNormalText,);  
          }  
        },  
    );  
  }  
}

Noticed a problem with the OnlineRoom.fromJson() method. I wrote a short piece of code to check in the main() function. But I see that the OnlineRoom.fromJson() method works properly. Why is there a difference between the fromJson() function when pulling data from Firebase and the available data?

final object = OnlineRoom.fromJson(roomJsonSnippet);  
logger.i(object); // no error, the object is logged correctly
Map<String, dynamic> roomJsonSnippet =  {  
    "winCount": 5,  
     "historyBoard": {  
         "cells": {  
             "0": [  
                 {  
                     "column": 0,  
                     "row": 0,  
                     "state": "normal",  
                     "content": "noSeed"  
                   },  
                 {  
                     "column": 1,  
                     "row": 0,  
                     "state": "normal",  
                     "content": "noSeed"  
                   }  
               ],  
             "1": [  
                 {  
                     "column": 0,  
                     "state": "normal",  
                     "row": 1,  
                     "content": "noSeed"  
                   },  
                 {  
                     "column": 1,  
                     "row": 1,  
                     "state": "normal",  
                     "content": "noSeed"  
                   }  
               ]  
           },  
         "rowCount": 2,  
         "columnCount": 2  
       },  
     "name": "Untitled Room",  
     "historyRoundIndex": 0,  
     "id": "ec483c14-f414-44ae-bea1-b84e409331f0",  
     "state": "playing",  
     "rounds": [  
         {  
             "historyTurns": [],  
             "currentPlayerIndex": 0,  
             "_historyPlayerIndex": 0,  
             "players": [  
                 {  
                     "score": 0,  
                     "finalScore": null,  
                     "seed": "cross",  
                     "name": "Player 1",  
                     "initialScore": 0,  
                     "index": 0  
                   },  
                 {  
                     "score": 0,  
                     "finalScore": null,  
                     "seed": "nought",  
                     "initialScore": 0,  
                     "name": "Player 2",  
                     "index": 1  
                   }  
               ],  
             "historyTurnIndex": 0,  
             "winTurnIndex": null,  
             "index": 0,  
             "currentTurnIndex": 0,  
             "winnerIndex": null,  
             "turns": []  
           }  
       ],  
     "board": {  
         "cells": {  
             "0": [  
                 {  
                     "column": 0,  
                     "state": "normal",  
                     "row": 0,  
                     "content": "noSeed"  
                   },  
                 {  
                     "column": 1,  
                     "row": 0,  
                     "state": "normal",  
                     "content": "noSeed"  
                   }  
               ],  
             "1": [  
                 {  
                     "column": 0,  
                     "state": "normal",  
                     "row": 1,  
                     "content": "noSeed"  
                   },  
                 {  
                     "column": 1,  
                     "row": 1,  
                     "state": "normal",  
                     "content": "noSeed"  
                   }  
               ]  
           },  
         "rowCount": 2,  
         "columnCount": 2  
       },  
     "currentRoundIndex": 0  
   }
1

There are 1 best solutions below

2
Jeanie Cho On

Since the type is not indicated from firestore data, I suppose you should cast type like

Map<String, dynamic> json = snapshot.data!.data()! as Map<String, dynamic>;