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

相关推荐
玖夜Kty38 分钟前
国内环境修改 flutter.bat 来设置 flutter 的网络环境
flutter
LinXunFeng2 小时前
Flutter - GetX Helper 助你规范应用 tag
flutter·github·visual studio code
阅文作家助手开发团队_山神11 小时前
第五章:Flutter Quill渲染原理深度剖析:Delta到RichText的华丽转身
flutter
未来猫咪花11 小时前
# Flutter状态管理对比:view_model vs Riverpod
flutter·ios·android studio
阅文作家助手开发团队_山神1 天前
第四章(下) Delta 到 HTML 转换:块级与行内样式渲染深度解析
flutter
MaoJiu1 天前
Flutter造轮子系列:flutter_permission_kit
flutter·swiftui
阅文作家助手开发团队_山神1 天前
第四章(下):Delta 到 HTML 转换的核心方法解析
flutter
xiaoyan20151 天前
flutter3.32+deepseek+dio+markdown搭建windows版流式输出AI模板
flutter·openai·deepseek
阅文作家助手开发团队_山神1 天前
第四章(上):HTML 到 Delta 转换的核心方法解析
flutter
stringwu1 天前
Flutter高效开发利器:Riverpod框架简介及实践指南
flutter