Flutter: Event Channels
Flutter is the latest in mobile SDKs that offers a lot out of the box in both its SDK and developer tools to produce applications quickly and easily. Check out other blogs that go into great detail as to the benefits of Flutter.
Flutter does not replace the need to communicate directly to native modules written in Java or Swift. You still need the native code to access the underlying mobile hardware or to do computationally heavy operations. This is similar to how the React-Native SDK is designed. While both SDKs are similar in design they differ greatly in implementation.
I’m not going to discuss the merits of one SDK over the other. Instead I want to explore one aspect of communications and that is from the native code to your Flutter app.
The documentation for Flutter is well written and detailed. The section on platform channels, the method to communicate with native code, is especially so with lots of detailed examples. However the document only explores the communications from your Flutter app to the native code and not the other direction.
Use Cases for Native Code Access
Implementing and using the MethodChannel
interface is like an RPC call: you invoke a method from your Flutter app to the native code, the native code does something and finally responds with a success or error. This call could be to get the current battery status, network information or temperature data. Once the native side has responded, it can no longer send more information until the next call.
I am interested in streaming data from the native code to my Flutter app. This could include continuously updating BLE or WiFi scanning results, accelerometer and gyro, or even periodic status updates from intensive data collection.
After finding the Java API docs, it didn’t take long to figure out that I wanted to use the EventChannel.StreamHandler
interface. Dart also has native support for Streams and so this was a welcome sight coming from an Akka/Monix/Rx background.
Native Code Emitter
Adding a new platform channel to stream data from native code was much easier than I was initially expecting. You simply create an implementation of the StreamHandler
interface and emit your events.
To ensure that this example will work on a majority of Android phones, I will use the RxJava library to emit a timed interval as an event. Again these events could be anything that you need streamed to your Flutter application.
Dart Code Receiver
Dart has built in support for Streams and the EventChannel
uses the capability of streams to signal when the native code should start to emit events and when to stop. To start the event emitter from the native side, just listen
to the platform channel stream
. When you are done just cancel
the subscription.
Since I want to display the intervals from the native code, my _updateTimer()
method simply sets the state in my widget.
The following log output displays an example that begins the subscription, emitting and receiving of events, and cancelling of the channel.
W/eventchannelsample(32641): adding listener
W/eventchannelsample(32641): emitting timer event 0
I/flutter (32641): Timer 0
W/eventchannelsample(32641): emitting timer event 1
I/flutter (32641): Timer 1
W/eventchannelsample(32641): emitting timer event 2
I/flutter (32641): Timer 2
W/eventchannelsample(32641): emitting timer event 3
I/flutter (32641): Timer 3
W/eventchannelsample(32641): emitting timer event 4
I/flutter (32641): Timer 4
W/eventchannelsample(32641): emitting timer event 5
I/flutter (32641): Timer 5
W/eventchannelsample(32641): cancelling listener
W/eventchannelsample(32641): adding listener
W/eventchannelsample(32641): emitting timer event 0
I/flutter (32641): Timer 0
W/eventchannelsample(32641): emitting timer event 1
I/flutter (32641): Timer 1
And that’s all there is to it!
Final Thoughts
It has been a fun journey learning and using Flutter. The ability to invoke native methods and emit events from native code with such little ceremony is a joy.
To the credit of both the Flutter and Dart teams, it took longer to write this blog post that implementing the example. Thank you to both the Flutter and Dart teams for making application development this fun and easy!
Here is my full source code to the sample application. The repository has two commits: the first from the flutter init
command; the second of all the changes I made.