Rob Okin
Rob Okin

Reputation: 173

How to add event listeners in Flutter?

I'm pretty new to Flutter and experimenting with the SDK. I'm working on a simple app that has a countdown in the background and want to trigger an event at certain intervals. For example, when clock reaches one minute remaining, send a push notification. In general, I'm trying to get a feel for how to monitor certain activities such as time and usage of the app and once certain conditions are met, trigger other things. Is it as simple as an if-else statement placed in the right place?

What kind of thing am I looking for to implement this?

Thanks in advance.

Upvotes: 14

Views: 59894

Answers (4)

Somen Das
Somen Das

Reputation: 506

Check this package: event_handeler

This flutter package gives you intuitive methods just like JavaScript event APIs. For dispatching custom events let's assume when I add something to secureStorage

_storage.write(key: 'filterBy', value: "clear filters").then((value) {
dispatchCustomEvent("clear filters","filterChange");
});

To listen to this particular event put this in initState under any function:

addCustomEventListener("filterChange", (eventvalue){
print(eventvalue);//prints clear filters
//do something you want when the event happens
    
});

Methods

  • dispatchCustomEvent(eventvalue,eventType)
  • addCustomEventListener(eventType, callback)

callback have the value of eventvalue

Upvotes: 0

Thanthu
Thanthu

Reputation: 5108

You can use ValueNotifier for this.

When value is replaced with something that is not equal to the old value as evaluated by the equality operator ==, this class notifies its listeners.

Helpful Medium link

Upvotes: 6

James Gardiner
James Gardiner

Reputation: 402

The following is a better example of an event listener based on Streams that I have found to work.

In the widget you want to listen to..

class CmVideoPlayer extends StatefulWidget {
  String titlePlaying;

  StreamController changeController = StreamController<VideoPlayerEvent>();

  CmVideoPlayer({Key key, @required this.titlePlaying})
      : assert(titlePlaying != null), super(key: key);

    @override
    _CmVideoPlayerState createState() => _CmVideoPlayerState();

}

See the line "StreamController changeController = StreamController();" that uses a small class VideoPlayerEvent to carry the message.

class VideoPlayerEvent {
  var eventType;
  var eventMessage;

  VideoPlayerEvent(this.eventType, this.eventMessage);
}

Then in the STATEFULLWIDGET...

Refer the the stream as

class _CmVideoPlayerState extends State<CmVideoPlayer> {
    void Member() {
        widget.changeController.add(new VideoPlayerEvent('state', 'finished'));
    }
}

As it is inside the _CmVideoPlayerState class, and using the ability to reach into the parent class via the widget variable.

Then in the area of the code using the widget, and to listen for the messages.. To listen for the messages

CmVideoPlayer myPlayer = CmVideoPlayer();
myPlayer.changeController.stream.listen((e) {
     print('Reciever event from CmVideoPlayer: ' + e.eventMessage.toString());
}

That should do it. HOWEVER, this only allows ONE listener at a time. After I got this going, I moved on. But plan to implement a multi listener down the track.

Maybe some one can expand on this. I am keeping it as simple as possible. If some one has a multi listener example. Please post here.

Upvotes: 5

Andrii Turkovskyi
Andrii Turkovskyi

Reputation: 29468

I prefer to use streams for such tasks

Stream<int> timer = Stream.periodic(Duration(seconds: 1), (int count) => count);
...
_MyTextWidget(timer)

and my widget

class _MyTextWidget extends StatefulWidget {
  _MyTextWidget(this.stream);

  final Stream<int> stream;

  @override
  State<StatefulWidget> createState() => _MyTextWidgetState();
}

class _MyTextWidgetState extends State<_MyTextWidget> {
  int secondsToDisplay = 0;

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
        stream: widget.stream,
        builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
          return snapshot.hasData ? Text(snapshot.data.toString()) : Text('nodata');
        });
  }
}

Upvotes: 7

Related Questions