An In-Depth Dive Into Streaming Data Across Platform Channels on Flutter

In this tutorial, you’ll learn how to use Platform Channels to stream data into your Flutter app. By Wilberforce Uwadiegwu.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 4 of 4 of this article. Click here to view the first page.

Streaming Bytes on iOS

In Constants.swift, add a new member to Constants:

static let eof = -0xFFFFFF

Declare the event name in AppDelegate below networkEventChannel like this:

private let imageEventChannel = "platform_channel_events/image"

Next, you’ll set the handler of the image stream events.

Navigate to application(). Inside AppDelegate, above GeneratedPluginRegistrant.register(with: self), add:

FlutterEventChannel(name: imageEventChannel, binaryMessenger: controller.binaryMessenger)
   .setStreamHandler(ImageStreamHandler())

Then, navigate to ImageStreamHandler.swift. In ImageStreamHandler, below onCancel(), paste:

func dispatchImageEvents(quality: Double, chunkSize: Int, eventSink: @escaping FlutterEventSink) -> Void {
    
    // Load the image into memory
    guard let image  = UIImage(named: "cute_dog_unsplash.jpg"),
          
    // Compress the image using the quality passed from Flutter
    let data = image.jpegData(compressionQuality: CGFloat(quality)) else {return}
    
    // Get the size of the image
    let length = data.count
    
    // Dispatch the first event (which is the size of the image)
    eventSink(length)
    
    DispatchQueue.global(qos: .background).async {
        
        // Split the image into chunks using the chunkSize passed from Flutter
        let parts = length / chunkSize
        var offset = 0
        
        // Repeat this block of statements until you have dispatched the last chunk
        repeat {
            // Mimic buffering with a 1 mill delay
            usleep(1000)
            
            let thisChunkSize = ((length - offset) > parts) ? parts : (length - offset)
            let chunk  = data.subdata(in: offset..<offset + thisChunkSize)
            
            // Dispatch each chunk to Flutter
            eventSink(chunk)
            offset += thisChunkSize
            
        } while (offset < length)
        
        // Dispatch an event to indicate the end of the stream
        eventSink(Constants.eof)
    }
}

Just like on Android, the above code is just chunking an image into a list of bytes.

Finally, you need to pass the arguments you passed from Flutter to dispatchImageEvents.

Paste this function in onListen(), right above the return statement:

let args = arguments as! Dictionary<String, Any>
let quality = args["quality"] as! Double
let chunkSize = args["chunkSize"] as! Int
dispatchImageEvents(quality: quality, chunkSize: chunkSize, eventSink: events)

Run the app on iOS and tap Stream Image. You'll see something like this:

Loading a dog image

This beautiful dog photo is by Marliese Streefland on Unsplash

Congratulations! You did such an amazing job. Now, go out there and continue building world-class apps!

Where to Go From Here?

You can find the completed project inside completed in files you downloaded earlier or by clicking Download Materials at the top or bottom of this tutorial.

In this tutorial, you learned how to stream from predetermined events to arbitrary bytes from native Android and iOS to Flutter.

To learn more about the differences between MethodChannel and EventChannel, see this Stackoverflow discussion. If you're interested in knowing how Flutter Platform Channels works under the hood, checkout this post by Mikkel Ravn.

I hope you enjoyed this tutorial. If you have any questions or comments, please join the forum discussion below!