Flutter与原生通讯的channel

在 Flutter 里,和原生代码通讯的通道主要有三种,分别是MethodChannelEventChannelBasicMessageChannel,下面为你详细介绍它们的适用场景和使用方法。

1. MethodChannel

适用场景

适用于 Flutter 和原生之间进行方法调用,也就是 Flutter 调用原生方法,原生返回结果,或者原生调用 Flutter 方法,Flutter 返回结果。比如调用原生的相机、分享功能等。

使用方法

以下是一个简单的示例,展示了 Flutter 如何通过 MethodChannel 调用原生 iOS 的方法。

Flutter 端代码

dart

dart 复制代码
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  static const platform = MethodChannel('samples.flutter.dev/battery');

  Future<void> _getBatteryLevel() async {
    String batteryLevel;
    try {
      final int result = await platform.invokeMethod('getBatteryLevel');
      batteryLevel = 'Battery level: $result%';
    } on PlatformException catch (e) {
      batteryLevel = "Failed to get battery level: '${e.message}'.";
    }

    print(batteryLevel);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Battery Level'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: _getBatteryLevel,
            child: const Text('Get Battery Level'),
          ),
        ),
      ),
    );
  }
}

iOS 端代码(Swift)

swift

swift 复制代码
import Flutter
import UIKit

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    let batteryChannel = FlutterMethodChannel(name: "samples.flutter.dev/battery", binaryMessenger: controller.binaryMessenger)
    batteryChannel.setMethodCallHandler {
      (call: FlutterMethodCall, result: @escaping FlutterResult) in
      if call.method == "getBatteryLevel" {
        self.receiveBatteryLevel(result: result)
      } else {
        result(FlutterMethodNotImplemented)
      }
    }

    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

  private func receiveBatteryLevel(result: @escaping FlutterResult) {
    UIDevice.current.isBatteryMonitoringEnabled = true
    if UIDevice.current.batteryState == .unknown {
      result(FlutterError(code: "UNAVAILABLE",
                          message: "Battery info unavailable",
                          details: nil))
    } else {
      result(Int(UIDevice.current.batteryLevel * 100))
    }
  }
}

2. EventChannel

适用场景

适用于原生向 Flutter 发送连续的事件流,比如传感器数据、网络状态变化等。

使用方法

以下是一个简单的示例,展示了 iOS 端如何通过 EventChannel 向 Flutter 发送模拟的传感器数据。

Flutter 端代码

dart

php 复制代码
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  static const stream = EventChannel('samples.flutter.dev/sensor');

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Sensor Data'),
        ),
        body: StreamBuilder(
          stream: stream.receiveBroadcastStream(),
          builder: (context, snapshot) {
            if (snapshot.hasError) {
              return Text('Error: ${snapshot.error}');
            }
            if (snapshot.hasData) {
              return Text('Sensor data: ${snapshot.data}');
            }
            return const Text('Waiting for data...');
          },
        ),
      ),
    );
  }
}

iOS 端代码(Swift)

swift

swift 复制代码
import Flutter
import UIKit

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    let eventChannel = FlutterEventChannel(name: "samples.flutter.dev/sensor", binaryMessenger: controller.binaryMessenger)
    eventChannel.setStreamHandler(SensorStreamHandler())

    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

class SensorStreamHandler: NSObject, FlutterStreamHandler {
  private var timer: Timer?
  private var eventSink: FlutterEventSink?
  private var counter = 0

  func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
    eventSink = events
    timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in
      guard let self = self else { return }
      if self.counter < 10 {
        self.eventSink?(self.counter)
        self.counter += 1
      } else {
        self.eventSink?(FlutterEndOfEventStream)
        self.timer?.invalidate()
      }
    }
    return nil
  }

  func onCancel(withArguments arguments: Any?) -> FlutterError? {
    timer?.invalidate()
    eventSink = nil
    return nil
  }
}

3. BasicMessageChannel

适用场景

适用于 Flutter 和原生之间进行简单的消息传递,比如传递字符串、JSON 数据等。

使用方法

以下是一个简单的示例,展示了 Flutter 和 iOS 之间通过 BasicMessageChannel 传递字符串消息。

Flutter 端代码

dart

dart 复制代码
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  static const messageChannel = BasicMessageChannel<String>('samples.flutter.dev/message', StringCodec());

  Future<void> _sendMessage() async {
    try {
      final String reply = await messageChannel.send('Hello from Flutter!');
      print('Received reply: $reply');
    } catch (e) {
      print('Error sending message: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Message Channel'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: _sendMessage,
            child: const Text('Send Message'),
          ),
        ),
      ),
    );
  }
}

iOS 端代码(Swift)

swift

swift 复制代码
import Flutter
import UIKit

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    let messageChannel = FlutterBasicMessageChannel(name: "samples.flutter.dev/message", binaryMessenger: controller.binaryMessenger, codec: FlutterStringCodec.sharedInstance())
    messageChannel.setMessageHandler { (message: Any?, reply: @escaping (Any?) -> Void) in
      if let messageString = message as? String {
        print("Received message: (messageString)")
        reply("Hello from iOS!")
      } else {
        reply(nil)
      }
    }

    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

这些示例展示了三种通道在 Flutter 和 iOS 之间的基本使用方法。

相关推荐
明似水15 小时前
2025年Flutter初级工程师技能要求
flutter
程序猿阿伟19 小时前
《从像素到身份:Flutter如何打通社交应用人脸识别的技术闭环》
flutter
周胡杰2 天前
鸿蒙接入flutter环境变量配置windows-命令行或者手动配置-到项目的创建-运行demo项目
javascript·windows·flutter·华为·harmonyos·鸿蒙·鸿蒙系统
程序猿阿伟2 天前
《React Native与Flutter:社交应用中用户行为分析与埋点统计的深度剖析》
flutter·react native·react.js
肥肥呀呀呀2 天前
在Flutter上如何实现按钮的拖拽效果
前端·javascript·flutter
WDeLiang3 天前
Flutter - UIKit开发相关指南 - 导航
flutter·ios·dart
程序猿阿伟3 天前
《Flutter社交应用暗黑奥秘:模式适配与色彩的艺术》
前端·flutter
融云3 天前
集成指南:如何采用融云 Flutter IMKit 实现双端丝滑社交体验
flutter
EndingCoder4 天前
跨平台移动开发框架React Native和Flutter性能对比
flutter·react native·react.js
Double Point4 天前
`RotationTransition` 是 Flutter 中的一个动画组件,用于实现旋转动画效果
flutter