marcojakob / dart-event-bus

An Event Bus using Dart Streams for decoupling applications
MIT License
755 stars 82 forks source link

Not Firing from second page #37

Closed Naguchennai closed 4 years ago

Naguchennai commented 4 years ago

main page

       @override
  void initState() {
    _listen();
  }

  var result;
  void _listen(){
    eventBus.on<UserLoggedInEvent>().listen((event){
      log('eventevent'+ event.text);
    });
  }

and Second poge

        onTap: () => {
                      eventBus.fire(new UserLoggedInEvent('vvvvvvvvvvvv'))
       }
marcojakob commented 4 years ago

It's quite unlikely that this is a bug in EventBus. Please debug your application and check if the listener is actually being called.

Naguchennai commented 4 years ago

its work in same page ... but not work from onother page i also trey with

     StreamSubscription loginSubscription;

  loginSubscription = eventBus.on<UserLoggedInEvent>().listen((event) {
  print(event.text);
});

also not work

markathomas commented 4 years ago

same here, the listener is never fired from something on the backstack to a visible page

greg-fischer commented 4 years ago

Me too. Although I played around with the even class and can see it being hit when "fire" is called. I changed it like below to test:

class UserLoggedInEvent {
    Map userData;

    UserLoggedInEvent(this.userData){
        print("[EVENT] fired user logged in");
    }
}

Using above I can see the printed EVENT line. However, anywhere I'm listening for the events, nothing happens there on the actual "listen()".

None of the below prints:

void appEvenListeners() {

        eventBus.on().listen((event){
            print(" ...>>EVENT>>> ");
            print(event);
        });

        eventBus.on<UserLoggedInEvent>().listen((event) {
            // All events are of type UserLoggedInEvent (or subtypes of it).
            print("Got event in Main AppState for User Login");
            print(event);
        });

        eventBus.on<APIRequestComplete>().listen((event) {
            // All events are of type UserLoggedInEvent (or subtypes of it).
            print("Got event in Main AppState for API Finished");
            print(event);
        });
        eventBus.on<APIRequestError>().listen((event) {
            // All events are of type UserLoggedInEvent (or subtypes of it).
            print("Got event in Main AppState for API Error");
            print(event);
        });

    }
marcojakob commented 4 years ago

@greg-fischer How does the code look like where you initialize the event bus and fire it?

greg-fischer commented 4 years ago

@marcojakob Thanks for responding so quickly. I just happened to figure out my issue. Its because the eventBus needs to be a singleton. As your docs say, there should only be one eventBus in an app. Because I have Mixins and other classes, some that launch from a shared local package library, the eventBus instance created in main.dart or other main app dart files are not the same instance of the eventBus. In my system, I have an API class in a shared library, it knows nothing about the main.dart app unless I feed it objects. The API class also created an eventBus variable, making a new instance. So my events fired, but the app's listeners didn't catch them.

Just a suggestion, but you may want to add docs or suggest making a singleton class to import. That's what I did. And in my case its in my shared library so my API class and all my app can access the single instance. The way I read your docs I was thinking I had to make an eventBus property on each class, which makes a new instance each time. I wasn't sure how best to handle it, but the singleton class seems to work.

Thanks!!


import 'package:event_bus/event_bus.dart';

class EventService {

    EventBus eventBus;
    int instanceId = 0;

    static final EventService _eventService = EventService._internal();
    factory EventService() {
        return _eventService;
    }

    EventService._internal(){
        this.eventBus = new EventBus();
        this.instanceId++;
        print(" >>>> Event service started ${this.instanceId}");
    }
}

class UserLoggedInEvent {
    Map userData;

    UserLoggedInEvent(this.userData){
        print("[EVENT] fired user logged in");
    }
}

To fire events. Import your class and use the EventService().eventBus

EventService().eventBus.fire(UserLoggedInEvent({
  "username": usernameCtl.text.trim(),
  "thing": "Thing data",
}));

To listen:

EventService().eventBus.on<UserLoggedInEvent>().listen((event) {
  // All events are of type UserLoggedInEvent (or subtypes of it).
  print("Got event in Main AppState for User Login");
  print(event.userData['username']);
});

These show up in debug:

flutter: [EVENT] fired user logged in
flutter: Got event in Main AppState for User Login
flutter: greg
marcojakob commented 4 years ago

Ok, I'm glad you could find the issue and solve it.

There are multiple ways to use the EventBus and also to make it one instance only. It doesn't always have to be a singleton but a singleton is a way, of course.

greg-fischer commented 4 years ago

Just curious, how would you make EventBus a single instance throughout the app? I haven't been working in Flutter/dart for very long (less than a year, off-n-on) so I'm probably missing some smarter techniques.

marcojakob commented 4 years ago

In Dart you can use top-level variables or if you want testability and a fancy way you could use Provider. But a singleton like yours is certainly fine as well.

markathomas commented 4 years ago

Use a singleton

import 'package:event_bus/event_bus.dart';

class MyEventBus {
  static final MyEventBus _singleton = new MyEventBus._internal();

  EventBus eventBus;

  factory MyEventBus() {
    return _singleton;
  }

  MyEventBus._internal() {
    eventBus = new EventBus();
  }
}