Day16 开发套件 - 实作EventChannel

使用上跟MethodChannel类似,EventChannel即为MethodChannelStream的结合

Flutter 端:

首先同样先建立Channel并指定名称(记得所有通道名称都不能重复),然後要对Native 端传递来的讯息进行监听,通过EventChannel调用receiveBroadcastStream()来取得一个Stream物件,後续通过在Stream中新增监听来完成对 Native 端讯息的接收等操作

lib/batterylevel.dart

这边建立一个EvnetChannel来取得Native 端一个骰子持续摇出来的数字,并建立一个取得骰子讯息的Stream物件方法

  static const EventChannel _eventChannel = const EventChannel('dice_number');
 
	static Stream<int> get getRandomNumberStream {
    return _eventChannel.receiveBroadcastStream().cast();
  }

Native 端(Android):

android/.../BatterylevelPlugin.kt

这边一样要设置好EvnetChannel,指定名称(需要与Flutter 端使用的EvnetChannel名称相对应),并通过EvnetChannel呼叫setStreamHandler来注册一个MessageHandler来接收此通道讯息,这边不像预设的范例直接让BatterylevelPlugin实现setStreamHandler的接口,我们将接口的实现拉出来一个类别来实作,这样把实现接口的逻辑拉出去实作,BatterylevelPlugin才不会在功能变多时变得太复杂

所以建立一个RandomNumberStreamHandler.kt 来实现接口,这边每一秒骰一次骰子并将结果回传至Flutter 端

class RandomNumberStreamHandler : EventChannel.StreamHandler {
    private var sink: EventChannel.EventSink? = null
    private var handler: Handler? = null

    private val runnable = Runnable {
        sendNewRandomNumber()
    }

    private fun sendNewRandomNumber() {
        val randomNumber = (1..6).random()
        sink?.success(randomNumber)
        handler?.postDelayed(runnable, 1000)
    }

    override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
        sink = events
        handler = Handler()
        handler?.post(runnable)
    }

    override fun onCancel(arguments: Any?) {
        sink = null
        handler?.removeCallbacks(runnable)
    }
}

BatterylevelPlugin.kt 加上:

    private lateinit var eventChannel: EventChannel

    override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        //Added
        eventChannel = EventChannel(flutterPluginBinding.binaryMessenger, "dice_number")
        eventChannel.setStreamHandler(RandomNumberStreamHandler())
    }

    override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
        //Added
        eventChannel.setStreamHandler(null)
    }

Native 端(iOS):

一样可以把setStreamHandler的接口实现的逻辑拉出去实作,同样建立一个RandomNumberStreamHandler.swift 来实现接口,每一秒骰一次骰子并将结果回传至Flutter 端

ios/Classes/RandomNumberStreamHandler.swift

import Foundation
import Flutter

class RandomNumberStreamHandler: NSObject, FlutterStreamHandler{
    var sink: FlutterEventSink?
    var timer: Timer?
    
    @objc func sendNewRandomNumber() {
        guard let sink = sink else { return }
        
        let randomNumber = Int.random(in: 1..<7)
        sink(randomNumber)
    }
    
    func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
        sink = events
        timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(sendNewRandomNumber), userInfo: nil, repeats: true)
        return nil
    }
    
    func onCancel(withArguments arguments: Any?) -> FlutterError? {
        sink = nil
        timer?.invalidate()
        return nil
    }
}

ios/Classes/SwiftBatterylevelPlugin.swift

import Flutter
import UIKit

public class SwiftBatterylevelPlugin: NSObject, FlutterPlugin {
    public static func register(with registrar: FlutterPluginRegistrar) {
				//Added
        let eventChannel = FlutterEventChannel(name: "dice_number", binaryMessenger: registrar.messenger())
        let randomNumberStreamHandler = RandomNumberStreamHandler()
        eventChannel.setStreamHandler(randomNumberStreamHandler)
    }
}

<<:  面对自己阴暗面的修练

>>:  Day 16 Flask 前端

DAY 13 『 Realm 新增、修改、删除 』Part1

今天会分享如何搭配 Realm 实作出资料管理系统,然後用 TableView 显示。 成品: 在 ...

[Day30] 第三十课 Azure学习建议与深入浅出Azure常用服务小结

终於来到第30天了,每天写下来不知不觉就一个月了,记得第一课还在自我介绍, 转眼间已经要第三十课。这...

Day15 单纯贝氏分类器实作

https://github.com/PacktPublishing/Machine-Learni...

Day24 Plugin 从零开始到上架 - FlutterPlugin与 MethodCallHandler

InstagramBasicDisplayApiPlugin class InstagramBasi...

Day9 Goroutine

并发 vs并行 并发运算就是多线程运算,且并发(concurrency)并非并行(Paralleli...