1

我目前正在学习 Flutter,特别是与设备本身进行通信。

目前我已经设置了一个 MethodChannel,我收到一个字符串列表作为结果,但现在我想将其更改为通过 EventChannel 在流上接收这些字符串。

我知道我仍然必须依靠 MethodChannel 来触发 android 端的方法,然后通过 EventChannel 将数据(在我的情况下为字符串)发送回颤振。但我真的不知道如何让 EventChannel 只发送几个流(它们之间可能会有一点延迟..),因为我发现的每个关于 EventChannel 的教程都比对我的帮助更令人困惑:(

这是我目前通过 EventChannel 获取内容的代码:

颤振插件:

static const EventChannel messageChannel = EventChannel('eventChannelStream');

  Stream<String> get messageStream async* {
    messageChannel.receiveBroadcastStream().map((message) {
      return message;
    });
  }

android端的Kotlin代码:

class HelperPlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamHandler {

    private lateinit var channel: MethodChannel
    private var messageChannel: EventChannel? = null
    private var eventSink: EventChannel.EventSink? = null

    override fun onListen(arguments: Any?, eventSink: EventChannel.EventSink?) {
        this.eventSink = eventSink
    }

    override fun onCancel(arguments: Any?) {
        eventSink = null
        messageChannel = null
    }

    override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        channel = MethodChannel(flutterPluginBinding.binaryMessenger, "methodChannel")
        channel.setMethodCallHandler(this)

        messageChannel = EventChannel(flutterPluginBinding.binaryMessenger, "eventChannelStream")
        messageChannel?.setStreamHandler(this)
    }


... 
// Doing other stuff here

以及我想如何在 BLoC 中使用这些消息在事件之后将它们发送到 UI:

Stream<String> retrieveMessage(Stream<String> messageStream) async* {
  await for (String message in messageStream) {
    //await Future.delayed(const Duration(milliseconds: 1500));
    yield message;
  }
}
4

1 回答 1

1

好的,让它工作。这可能不是最好的方法,但至少它有效:)

所以这就是我的做法,也许它可以帮助别人:):

来自 Android 的响应的 Kotlin 代码:

class HelperPlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamHandler {

    private lateinit var channel: MethodChannel
    private var messageChannel: EventChannel? = null
    private var eventSink: EventChannel.EventSink? = null


    override fun onListen(arguments: Any?, eventSink: EventChannel.EventSink?) {
        this.eventSink = eventSink
    }

    override fun onCancel(arguments: Any?) {
        eventSink = null
        messageChannel = null
    }

    override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        channel = MethodChannel(flutterPluginBinding.binaryMessenger, "methodChannel")
        channel.setMethodCallHandler(this)

        messageChannel = EventChannel(flutterPluginBinding.binaryMessenger, "eventChannelStream")
        messageChannel?.setStreamHandler(this)
    }

    override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
        when (call.method) {
            "getPlatformVersion" -> {
                result.success(tellVersionNumber())
            }
            "tellJoke" -> {
                result.success(tellJoke())
            }
            "cantAnswer" -> {
                result.success(cantAnswer())
            }
            "whoAreYou" -> {
                result.success(whoAreYou())
            }
            "currentTime" -> {
                result.success(currentTime())
            }
            "upTime" -> {
                result.success(upTime())
            }
            "greetUser" -> {
                result.success(greetUser())
            }
            "systemInformation" -> {
                result.success(systemInformation())
            }
            else -> {
                result.notImplemented()
            }
        }
    }

    override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
        channel.setMethodCallHandler(null)
    }

// Here are Functions, which add Strings to the EventChannel via eventSink?.success("String to Add")

}

颤振插件:

class ChatbotHelper extends ChatbotInterface {
  static const MethodChannel _channel = MethodChannel('methodChannel');
  static const EventChannel messageChannel = EventChannel('eventChannelStream');

  Stream<String> get messageStream async* {
    await for (String message in messageChannel.receiveBroadcastStream().map((message) => message)){
      yield message;
    }
  }

  @override
  Future<void> platformVersion() async {
    await _channel.invokeMethod('getPlatformVersion');
  }

  @override
  Future<void> tellJoke() async {
        await _channel.invokeMethod('tellJoke');
  }
// other invokeMethods and answerQuestion function, which calls these invokeMethods depending on a String message

...

}

以下是我在 BLoC 中使用 Stream 的方式:

 Future<void> _initializeAnswerStream(
      InitializeMessageStreamEvent event, Emitter<ChatState> emit) async {
    try{
        await for(String message in retrieveMessageStream(_helper.messageStream)) {

        add(AddResponseMessageEvent(responseMessage: message));
      }
    }catch(e){
      print(e);
    }
  }

在我的 Widget Tree 中创建相应的 BlocProvider 时会调用此 BLoC-Event 以初始化 Stream 并等待消息。

编辑:修复了一些我重命名的值以在此处发布

于 2021-10-22T13:05:18.603 回答