0

I have a screen where I need to get a JSON file name from Firestore first and then load the asset JSON file. I usually use StreamBuilder for Firestore document snapshots and I can load JSON with a FutureBuilder. My question is how can I combine them? Or, is there any better way of doing what I mentioned?

As far as I know, FutureBuilder cannot work properly inside StreamBuilder, so it is not a choice I guess.

I get snapshots from Firestore as:

  UserModel _userDataFromSnapshot(DocumentSnapshot snapshot) {
    final userdata = snapshot.data();
    return UserModel(
      ...
    );
  }

  Stream<UserModel> get userData {
    return userCollection.doc(uid).snapshots()
      .map(_userDataFromSnapshot);
  }

And I load JSON as:

FutureBuilder(
  future: DefaultAssetBundle.of(context).loadString(fileName),
  builder: (context, snapshot) {
    if(snapshot.hasData) {
      final data = json.decode(snapshot.data.toString()).cast<String, dynamic>();
      ...

I appreciate any help or comment.

1 Answers1

0

You can try with some state management to get your stream and then once the data received from the stream, getting the JSON. I personally use Flutter Bloc, but it's up to you if you prefere another one like Riverpod.

If you are having trouble implementing the Stream with Flutter Bloc, here is a medium story that may help you: https://arnaudelub.medium.com/flutter-bloc-and-firestore-stream-the-perfect-match-if-used-the-right-way-5a4607f093a2

The bloc flow would be like this:

yield* event.map(watchUserData: (WatchUserData _) async* {
      await _userDatasStreamSubscription?.cancel();
      _userDatasStreamSubscription = _repository.getUserData().listen(
          (Either<FirestoreFailure, UserData> data) =>
              add(UserDataEvent.userDataReceived(data)));
    }, userDataReceived: (UserDatasReceived data) async* {
      yield data.data.fold(
        (failure) => 
           UserDataState.userDataLoadFailure(failure),
        (success) {
           final jsonData = await _jsonRepository.loadStringFromFilename(filenam);
           UserDataState.userDataLoadSuccess(userData: success, jsonData: jsonData));
          }
    });

I am using Either from Dartz plugin to handle the failures from my repositories, that's why i am using fold on my repository's methods.

Arnaud Delubac
  • 759
  • 6
  • 13