I have the next bloc:
sealed class CameraState extends Equatable {
const CameraState();
@override
List<Object> get props => [];
}
final class CameraInitial extends CameraState {}
final class CameraReady extends CameraState {
final CameraController cameraController;
const CameraReady({required this.cameraController});
@override
List<Object> get props => [cameraController];
}
final class CameraFailure extends CameraState {
final String error;
const CameraFailure({this.error = "CameraFailure"});
@override
List<Object> get props => [error];
}
final class CameraPermissionDenied extends CameraState {}
sealed class CameraEvent {}
final class CameraStopped extends CameraEvent {}
final class CameraInitialized extends CameraEvent {}
class CameraBloc extends Bloc<CameraEvent, CameraState> {
final CameraUtils cameraUtils;
final ResolutionPreset resolutionPreset;
final CameraLensDirection cameraLensDirection;
CameraController? _controller;
CameraBloc({
required this.cameraUtils,
this.resolutionPreset = ResolutionPreset.high,
this.cameraLensDirection = CameraLensDirection.back,
}) : super(CameraInitial()) {
on<CameraInitialized>(_onCameraInitialized);
on<CameraStopped>(_onCameraStopped);
}
Future _onCameraInitialized(
CameraInitialized event, Emitter<CameraState> emit) async {
try {
final isGranted = await cameraUtils.requestPermission();
if (!isGranted) {
emit(CameraPermissionDenied());
return;
}
final camera = await cameraUtils.findBestCamera(cameraLensDirection);
_controller =
await cameraUtils.createCameraController(camera, resolutionPreset);
await _controller!.initialize();
emit(CameraReady(cameraController: _controller!));
} on CameraException catch (error) {
_controller?.dispose();
emit(CameraFailure(error: error.description ?? error.toString()));
} catch (error) {
emit(CameraFailure(error: error.toString()));
}
}
Future _onCameraStopped(
CameraStopped event, Emitter<CameraState> emit) async {
_controller?.dispose();
emit(CameraInitial());
}
@override
Future<void> close() {
_controller?.dispose();
return super.close();
}
}
The problem is that it contains asynchronous event-to-state mappers, so if I will write a something like below:
bloc.add(CameraInitialized());
bloc.add(CameraStopped());
The state will be changes in order
CameraInitial -> CameraInitial -> CameraReady
not
CameraInitial -> CameraReady -> CameraInitial
It happens due to _onCameraInitialized()
execution takes enough long time and contains await
points, so execution turn is passed to _onCameraStopped()
before _onCameraInitialized()
called emit()
.
Is it possible to synchronize state order in such case? I think about a mutex but it doesn’t look as a right way.