Bloc: add state directly in Stream<State>

Created on 18 Mar 2020  路  6Comments  路  Source: felangel/bloc

Hi, @felangel I hope u doing well.
in my project, I need to show the progress of uploading file.
I use Dio and in this library, there is a callback that returns progress of uploaded file.

this is my code can u help to fix this problem
I want to yield a state in callback function or maybe add state directly into Stream.

```@override
Stream mapEventToState(
ProfilePictureEvent event,
) async* {
if (event is UploadProfilePicture) {
final ProgressCallback progressCallback = (count, total) {
logDebug(value: 'count: $count, total: $total');
// yield loading state here
}
};

  final result = await _apiService.updateProfilePicture(
    event.pictureFile,
    progressCallback,
  );
  if (result.success) {
    yield UploadProfileSuccessfulState();
  } else {
    yield UploadProfileFailedState(error: result.parseAllErrors());
  }
}

}```

thanks

question

All 6 comments

Hi @payam-zahedi 馃憢
Thanks for opening an issue!

In that case I would recommend adding an event to the bloc from within the callback so that it can be processed asynchronously.

Stream<ProfilePictureState> mapEventToState(
    ProfilePictureEvent event,
  ) async* {
     if (event is UploadProfilePicture) {
      final ProgressCallback progressCallback = (count, total)  {
        logDebug(value: 'count: $count, total: $total');
        add(UploadProgressChanged(count/total));
        }
      };

      final result = await _apiService.updateProfilePicture(
        event.pictureFile,
        progressCallback,
      );
      if (result.success) {
        yield UploadProfileSuccessfulState();
      } else {
        yield UploadProfileFailedState(error: result.parseAllErrors());
      }
    }
  }

@felangel thanks for your answer.
this is a good idea, but I found another way that maybe be more useful for my situation.
please check the below code and tell me your suggestion if it's possible for you.

```@override
Stream mapEventToState(
ProfilePictureEvent event,
) async* {
if (event is UploadProfilePicture) {
StreamController controller = new StreamController();

  controller.add(
    UploadProfileLoadingState(uploadPercentage: 0),
  );
  final ProgressCallback progressCallback = (count, total) {
    logDebug(value: 'count: $count, total: $total');
    logDebug(value: 'percent: ${(count / total * 100)}');

    if( total >= -1 ){
      controller.add(
        UploadProfileLoadingState(uploadPercentage: (count / total * 100)),
      );
    }
  };

  _apiService.updateProfilePicture(
    event.pictureFile,
    progressCallback,
  ).then((result){
    if (result.success) {
      controller.add(
        UploadProfileSuccessfulState(),
      );
    } else {
      controller.add(
        UploadProfileFailedState(error: result.parseAllErrors()),
      );
    }
  }).whenComplete((){
    controller.close();
  });

  yield* controller.stream;

}

}```

thanks

@payam-zahedi that works too but I would argue it's more complicated and involves much more code than just adding another event to the bloc. In any case, both approaches work 馃憤

thank you @felangel . I will work on it

Just an FYI: @felangel your solution processes UploadProgressChanged events only after updateProfilePicture has finished. So I ended up using @payam-zahedi solution.

@krokyze my suggestion was

if (event is UploadProfilePicture) {
      add(UploadProgessChanged(uploadPercentage: 0));

      final ProgressCallback progressCallback = (count, total) {
        logDebug(value: 'count: $count, total: $total');
        logDebug(value: 'percent: ${(count / total * 100)}');

        if( total >= -1 ) {
          add(UploadProgressChanged(uploadPercentage: (count / total * 100)));
        }
      };

      _apiService.updateProfilePicture(
        event.pictureFile,
        progressCallback,
      ).then((result){
        if (result.success) {
          add(UploadProfileSucceeded());
        } else {
          add(UploadProfileFailed(error: result.parseAllErrors()));
        }
      });
    }
  }

But both solutions should work so it's up to you which you prefer 馃憤

Was this page helpful?
0 / 5 - 0 ratings