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 之间的基本使用方法。

相关推荐
SoaringHeart2 小时前
Flutter最佳实践:键盘辅助视图输入框天添加图片附件
前端·flutter
心中有国也有家3 小时前
AtomGit Flutter 鸿蒙客户端:Canvas 绘制进阶-路径、渐变与混合模式
android·javascript·flutter·华为·harmonyos
程序员老刘4 小时前
Android 17的10个AI功能,国内用户真正能用的有几个?
android·flutter·ai编程
浮洋8 小时前
HabitGo:一个 Flutter 习惯追踪 App 的深度技术剖析
flutter
西西学代码8 小时前
Flutter---RefreshIndicator案例
flutter
西西学代码8 小时前
Flutter---RefreshIndicator
flutter
末代iOS程序员华仔9 小时前
从 Figma 到上架:使用 Codex 与 MCP 全流程实现 AI 聊天 App
flutter·ios·swift
西西学代码10 小时前
Flutter---StreamBuilder案例
javascript·windows·flutter
子非鱼942712 小时前
03-Flutter 鸿蒙实战 03:登录注册与本地会话持久化
网络·flutter·华为·harmonyos
AM艾玛12 小时前
Flutter 环境搭建实录
vscode·flutter