You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter侧如何订阅原生代码中创建的监听器?

Flutter侧订阅原生iOS监听器实现方案

一、如何从Flutter侧订阅监听器

你的iOS原生代码已实现注册状态监听器,要让Flutter侧接收状态变化,用EventChannel最合适——它专门处理持续事件流,比MethodChannel更适配监听器场景。具体步骤如下:

1. iOS原生端改造

在你的类中添加EventChannel相关变量,并实现StreamHandler协议:

import Flutter

class YourNativeClass: NSObject {
    var methodChannel: FlutterMethodChannel!
    var registrationEventChannel: EventChannel?
    var registrationEventSink: EventSink?
    var loggedIn = false
    var mCore: Core?
    var mRegistrationDelegate: CoreDelegateStub?

    init(channel: FlutterMethodChannel) {
        self.methodChannel = channel
        super.init()
        // 初始化EventChannel,通道名称需和Flutter侧完全一致
        registrationEventChannel = EventChannel(channel.binaryMessenger, name: "com.your.app/registration_state")
        registrationEventChannel?.setStreamHandler(self)
        self.initCore()
    }

    func initCore() {
        LoggingService.Instance.logLevel = LogLevel.Debug
                
        try? mCore = Factory.Instance.createCore(configPath: "", factoryConfigPath: "", systemContext: nil)
        try? mCore.start()
        
        // 改造监听器,添加事件发送逻辑
        mRegistrationDelegate = CoreDelegateStub(onAccountRegistrationStateChanged: { (core: Core, account: Account, state: RegistrationState, message: String) in
            NSLog("New registration state is \(state) for user id \( String(describing: account.params?.identityAddress?.asString()))\n")
            if state == .Ok {
                self.loggedIn = true
            } else if state == .Cleared {
                self.loggedIn = false
            }
            // 将状态数据封装为Map发送到Flutter
            self.registrationEventSink?([
                "loggedIn": self.loggedIn,
                "state": state.rawValue,
                "userId": account.params?.identityAddress?.asString(),
                "message": message
            ])
        })
        mCore?.addDelegate(delegate: mRegistrationDelegate!)
    }
}

// 实现StreamHandler协议,处理Flutter的订阅/取消订阅请求
extension YourNativeClass: StreamHandler {
    func onListen(withArguments arguments: Any?, eventSink: @escaping EventSink) {
        // 保存事件Sink,后续用来发送事件
        registrationEventSink = eventSink
        // 可选:发送初始状态给Flutter
        eventSink(["loggedIn": loggedIn, "state": mCore?.currentRegistrationState.rawValue, "message": "初始状态"])
    }
    
    func onCancel(withArguments arguments: Any?) {
        // 取消订阅时释放Sink,避免内存泄漏
        registrationEventSink = nil
    }
}

2. Flutter侧订阅事件

在Flutter代码中通过EventChannel监听原生发送的状态变化:

import 'package:flutter/services.dart';

class YourFlutterWidget extends StatefulWidget {
  const YourFlutterWidget({super.key});

  @override
  State<YourFlutterWidget> createState() => _YourFlutterWidgetState();
}

class _YourFlutterWidgetState extends State<YourFlutterWidget> {
  final MethodChannel _methodChannel = MethodChannel('com.your.app/main_channel');
  final EventChannel _registrationEventChannel = EventChannel('com.your.app/registration_state');
  StreamSubscription? _registrationSubscription;
  bool _isLoggedIn = false;

  @override
  void initState() {
    super.initState();
    // 先调用原生初始化方法(可选,建议确保初始化完成后再监听)
    _initNativeCore();
    // 订阅注册状态变化事件
    _subscribeToRegistrationState();
  }

  Future<void> _initNativeCore() async {
    try {
      await _methodChannel.invokeMethod('init');
      print('原生Core初始化完成');
    } on PlatformException catch (e) {
      print('初始化失败: ${e.message}');
    }
  }

  void _subscribeToRegistrationState() {
    _registrationSubscription = _registrationEventChannel.receiveBroadcastStream()
        .listen((event) {
          setState(() {
            _isLoggedIn = event['loggedIn'];
          });
          // 处理其他状态数据
          String? userId = event['userId'];
          int stateCode = event['state'];
          String message = event['message'];
          print('注册状态更新: 已登录=$_isLoggedIn, 用户ID=$userId, 状态码=$stateCode, 消息=$message');
        }, onError: (error) {
          print('监听注册状态出错: $error');
        });
  }

  @override
  void dispose() {
    // 页面销毁时取消订阅,避免内存泄漏
    _registrationSubscription?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text(_isLoggedIn ? '已登录' : '未登录'),
      ),
    );
  }
}

二、是否需要始终返回FlutterResult?

不需要,分两种场景:

  • FlutterResult仅用于一次性方法调用:比如Flutter调用原生的init方法,此时可以返回result(true)告知初始化成功,或返回错误信息,但不是强制要求——不过返回结果能让Flutter侧更精准处理流程。
  • 监听器的持续事件流不需要FlutterResult:这类场景用EventChannel的Sink发送事件即可,和FlutterResult无关。

只有处理Flutter通过MethodChannel发起的单次请求时,才需要调用FlutterResult返回结果(成功/失败/未实现),比如原生的MethodCall处理逻辑:

func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
    switch call.method {
    case "init":
        self.initCore()
        result(true) // 返回初始化成功
    default:
        result(FlutterMethodNotImplemented)
    }
}

内容的提问来源于stack exchange,提问作者steind.VY

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 20:23:11