How to resolve emit was called after an event handler completed normally bloc error?

3,489

What if rewrite listen to await for like this?

Future<void> onStarted(
  DownloadStarted event,
  Emitter<DownloadState> emit,
) async {
  try {
    await PermissionHandler.requestStoragePermission();
    response = await downloadFile();
    totalSize = response!.contentLength ?? 0;

    emit(DownloadInProgress(
      progress: received,
      totalSize: totalSize,
    ));

    await for (final value in response?.stream) {
      received += value.length;
      bytes.addAll(value);

      add(DownloadProgressed(progress: received));
      print('received value is $received');
    }

    await storeBookRepo.storePdf(
      bytes.toString(),
      bookTitle: 'bookTitle',
    );

    emit(DownloadCompleted());
  } catch (e) {
    emit(DownlaodFailed(errorMessage: '$e'));
  }
}
Share:
3,489
biniyam112
Author by

biniyam112

Updated on January 01, 2023

Comments

  • biniyam112
    biniyam112 over 1 year

    I am using flutter bloc to make download progress percentage displayed but I keep getting this problem. I figured the problem arises in the onDone method but I couldn't figure out how to fix it.

    ERROR :

    Exception has occurred. _AssertionError ('package:bloc/src/bloc.dart': Failed assertion: line 137 pos 7: '!_isCompleted': emit was called after an event handler completed normally. This is usually due to an unawaited future in an event handler. Please make sure to await all asynchronous operations with event handlers and use emit.isDone after asynchronous operations before calling emit() to ensure the event handler has not completed.

    BAD

     on<Event>((event, emit) {
        future.whenComplete(() => emit(...));
      });
    

    GOOD

      on<Event>((event, emit) async {
        await future.whenComplete(() => emit(...));
      });
    )
    

    CODE :

    
    import 'package:bloc/bloc.dart';
    import 'package:download_progress_with_bloc/downlaod_file.dart';
    import 'package:download_progress_with_bloc/download_event.dart';
    import 'package:download_progress_with_bloc/download_state.dart';
    import 'package:download_progress_with_bloc/permission_handler.dart';
    import 'package:download_progress_with_bloc/store_book_repo.dart';
    import 'package:http/http.dart' as http;
    
    class DownloadBloc extends Bloc<DownloadEvent, DownloadState> {
      DownloadBloc({required this.storeBookRepo}) : super(DownloadInitial()) {
        on<DownloadStarted>(onStarted);
        on<DownloadProgressed>(onProgressed);
      }
      final StoreBookRepo storeBookRepo;
    
      http.StreamedResponse? response;
      // StreamController? _controller;
      int received = 0;
      List<int> bytes = [];
      int totalSize = 0;
    
      @override
      Future<void> close() {
        return super.close();
      }
    
      Future<void> onStarted(
          DownloadStarted event, Emitter<DownloadState> emit) async {
        try {
          await PermissionHandler.requestStoragePermission();
          response = await downloadFile();
          totalSize = response!.contentLength ?? 0;
          emit(DownloadInProgress(progress: received, totalSize: totalSize));
          response?.stream.asBroadcastStream().listen((value) async {
            received += value.length;
            bytes.addAll(value);
            add(DownloadProgressed(progress: received));
            print('received value is $received');
          }).onDone(
            () async {
              await storeBookRepo
                  .storePdf(
                    bytes.toString(),
                    bookTitle: 'bookTitle',
                  )
                  .then((value) => emit(DownloadCompleted()));
              // emit(DownloadCompleted());
            },
          );
        } catch (e) {
          emit(DownlaodFailed(errorMessage: '$e'));
        }
      }
    
      void onProgressed(DownloadProgressed event, Emitter<DownloadState> emit) {
        emit(DownloadInProgress(progress: event.progress, totalSize: totalSize));
      }
    
    
    }