flutter bloc calling an event in a class doesn't work
Asked Answered
S

1

0

I have a class where I have to call an event from my bloc chat_bloc. Im not able to call the event, since I don't have any context. When I try to add the ChatBloc to my SocketRepository im totally lost here.. This is my class:

class SocketRepository {
  ...
  socket.on('receive_message', (jsonData) => {
  print('****** receive message called $jsonData'),
  // <- I need to call my chat_bloc event, but i don't have any context...
  
});
..

This is my ChatBloc which needs 2 parameters (minified important part):

class ChatBloc extends Bloc<ChatEvent, ChatState> {
  final DatabaseRepository _databaseRepository;
  final SocketRepository _socketRepository;
  
  ChatBloc(_databaseRepository, _socketRepository) : super(ChatInitial()) {
    on<LoadChat>((event, emit) async {

My best result i could achieve with the error I have:

class SocketRepository {
late ChatBloc chatbloc;
...
socket.on('receive_message', (jsonData) => {
chatbloc.add(ReceiveMessage()),
..

Unhandled Exception: LateInitializationError: Field 'chatbloc' has not been initialized.

I dont know how to inizialize it in a correct way..

Straightforward answered 28/7, 2022 at 8:37 Comment(0)
J
2

From the fragment you have shown it looks like you didn't initialize chatBot inSocketRepository. You have used late and didn't initalize it:

class SocketRepository {
late ChatBloc chatbloc; <--
...
socket.on('receive_message', (jsonData) => {
chatbloc.add(ReceiveMessage()),
..

Changing it to final and passing bloc to Repository would solve the issue but its BAD usage of Bloc.

The truth is Bloc should never be passed into repository.

If you want to communicate from the repository to Bloc, expose a stream on Repository and in the Bloc listen for the values in it:

class SocketRepository{

Stream<SocketMessages> get messages =>
      messagesStreamController.stream.asBroadcastStream();

and in Bloc constructor listen to the stream:

class ChatBloc extends Bloc<ChatEvent, ChatState> {
  final DatabaseRepository _databaseRepository;
  final SocketRepository _socketRepository;
  
  ChatBloc(_databaseRepository, _socketRepository) : super(ChatInitial()) {
    on<LoadChat>((event, emit) async {...}
    
  _socketRepository.messages.listen( (message) => 
    add(SocketMessageEmitted(message: message)));

This way you dont have circular dependency of SocketRepository injecting ChatBloc and ChatBloc injecting SocketRepository

Jase answered 28/7, 2022 at 10:53 Comment(7)
thank you very much for your answer and for providing a better appraoch, i want to follow your appraoch now. do i get it right, that i have to call messagesStreamController.sink.add(message) in my socketrepository then ony m socket.on('receive_message', ?Straightforward
it seems like this is the way to go, thank you very much!Straightforward
Exactly! Let me know if you have any other concerns, this one should work like a charm - this is the general approach i would suggest to have separated layers of responsibility - Bloc doesn't have to be in Repository, and repository exposes information to whatever wants to listen to it.Jase
It works perfectly fine. Im still pretty new to bloc, for me it was really hard since the ressources from the web are way different to the flutter_bloc 8.x update. For my case its also a little "over the top" to create librarys for the repositorys i have, i simply hold them in my app folder structure without adding them in the pubspec.yaml. Besides that im using MultiRepositoryProvider and MultiBlocProvider pretty early in my app so everything important is in scope, and excluding my case described in my question, it worked perfectly fine, since I could manage everything with my widget treeStraightforward
If this sounds fine for you and you confirm this is clean, feel free to give me a feedback. The case described in my question was the one and only where I didn’t have direct access to the context. And if there will be another one I can handle it with your answer now in a nice way.Straightforward
Sure it makes sense - Bloc's are powerfull if used well - remember to provide them as low asJase
@MarcelDz I think it would be helpful to read up this on the usage of late modifier stackoverflow.com/a/69683423Recalcitrate

© 2022 - 2024 — McMap. All rights reserved.