skip to Main Content

I want to call the function we defined in a stateful widget class when a notification comes to the phone, so I need to use it in another class.

For example:

class ContactListPage extends StatefulWidget {
   @override
   _ContactListPageState createState() => _ContactListPageState();
}

class _ContactListPageState extends State<ContactListPage>{

     doSomething(){
         print("do something");
     }

}
-------------------------------------------------- ----------------------------------------

class PushMessageManager {
  configureNotificationsActions() async {
     FirebaseMessaging.onMessage.listen((RemoteMessage remoteMessage) {

       if (remoteMessage.data.isNotEmpty) {

         if (remoteMessage.data["type"] == "message") {

             // ContactListPage.doSomething();
         }
       }
     }
}

I tried calling directly, but I couldn’t get what I wanted. What method should I use? Thank you for your help.

2

Answers


  1. I will suggest you to use event_bus to achieve what you want.

    demo code:

    class PushEvent{}
    
    class ContactListPage extends StatefulWidget {
      @override
      _ContactListPageState createState() => _ContactListPageState();
    }
    
    class _ContactListPageState extends State<ContactListPage>{
    
      late final StreamSubscription<PushEvent> _subscription;
    
      @override
      void initState() {
        super.initState();
        _subscription = EventBus().on<PushEvent>().listen((event) {
          doSomething();
        });
      }
    
      doSomething(){
        print("do something");
      }
    
      @override
      void dispose() {
        super.dispose();
        _subscription.cancel();
      }
    
    }
    
    class PushMessageManager {
      configureNotificationsActions() async {
        FirebaseMessaging.onMessage.listen((RemoteMessage remoteMessage) {
    
          if (remoteMessage.data.isNotEmpty) {
    
            if (remoteMessage.data["type"] == "message") {
              EventBus().fire(PushEvent());
              // ContactListPage.doSomething();
            }
          }
        });
      }
    }
    
    
    Login or Signup to reply.
  2. The _ContactListPageState is private (as indicated by the _, so you won’t be able to see the function.

    If you want to call a method in the state of a StatefulWidget, you can use a GlobalKey, like in this other answer: https://stackoverflow.com/a/46545141/15469537

    Steps:

    1. Make the _ContactListPageState public (refactor it to remove the _)
    2. Make sure all fields in the State you don’t want to make public are private (start with _)
    3. Create a GlobalKey in a main/parent Widget (which you can use in your message handler)
    final contactListPageKey = GlobalKey<ContactListPageState>();
    
    // pass it as key to the contact list page
    return ContactListPage(key: contactListPageKey);
    
    1. Use this key to access the state
    if (remoteMessage.data["type"] == "message") {
      // call doSomething if the state exists. 
      // Since the key is Global, you cannot have the page open twice
      contactListPageKey.currentState?.doSomething();
    }
    

    Note that if the Widget is not mounted, this will not call the function at all, so make sure to think about the different possible states of the app when the message is received.

    Recommendation

    It’s recommended to have a global/static function to handle notifications which can, for instance, store something in the SharedPreferences so that the rest of the app has access to it when needed.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search