in my class Repository()
I have two streamcontrollers
running who are listening to changes.
final remoteStreamController = StreamController<dynamic>.broadcast();
Stream<dynamic> get remoteId =>
remoteStreamController.stream.asBroadcastStream();
final localStreamController = StreamController<dynamic>.broadcast();
Stream<dynamic> get localJoined =>
localStreamController.stream.asBroadcastStream();
now when there is an event in my app Im using sink
to provide informations threw them, so my bloc.dart
where im listening to stream changes can do some work in my app.
class GameBloc extends Bloc<GameBlocEvent, GameBlocState> {
final Repository repository;
VideocallBloc(this._agoraRepository) : super(VideocallInitial()) {
...
repository.localJoined.listen((res) {
repository.lastLocal = res["localJoined"];
repository.lastRemote = res["remoteId"];
add(UpdateVideoCall(engine: res["engine"], joined: repository.lastLocal ?? false, remote: repository.lastRemote ?? -1));
});
repository.remoteId.listen((res) {
repository.lastLocal = res["localJoined"];
repository.lastRemote = res["remoteId"];
add(UpdateVideoCall(engine: res["engine"], joined: repository.lastLocal ?? false, remote: repository.lastRemote ?? -1));
});
when the bloc doesn't need the state anymore it calls the close() function, where im closing the streams and some other stuff from my app.
this is the part in my bloc.dart
:
@override
Future<void> close() async {
//cancel streams
await _repository.localStreamController.close();
await _repository.remoteStreamController.close();
await _repository.engine?.leaveChannel();
await _repository.engine?.destroy();
await super.close();
}
If I need it again instead of creating the streams again, it throws me an error:
E/flutter ( 6080): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Bad state: Cannot add new events after calling close
Actually, it wants to call sink
in my Repository()
again, but it doesn't find my two streams. How can I recall those streams again? I thought it does it automatically.
CodePudding user response:
Consider closing the stream with StreamSubscription instead of closing the repository stream directly as another bloc can be listening to the repository stream and it can cause a problem
class GameBloc extends Bloc<GameBlocEvent, GameBlocState> {
final Repository repository;
VideocallBloc(this._agoraRepository) : super(VideocallInitial()) {
localJoinedSubscription = repository.localJoined.listen((res) {
repository.lastLocal = res["localJoined"];
repository.lastRemote = res["remoteId"];
add(UpdateVideoCall(engine: res["engine"], joined: repository.lastLocal ?? false, remote: repository.lastRemote ?? -1));
});
remoteIdSubscription = repository.remoteId.listen((res) {
repository.lastLocal = res["localJoined"];
repository.lastRemote = res["remoteId"];
add(UpdateVideoCall(engine: res["engine"], joined: repository.lastLocal ?? false, remote: repository.lastRemote ?? -1));
});
}
late final StreamSubscription localJoinedSubscription;
late final StreamSubscription remoteIdSubscription;
@override
Future<void> close() async {
//cancel streams
//this just make sures the current bloc closes the stream you are listening to
localJoinedSubscription.cancel();
remoteIdSubscription.cancel();
//any other thing you want to close
await super.close();
}
}