Flutter Channel 类型与用法

在Flutter中,Platform Channels 是一种用于与原生代码(如iOS和Android)进行通信的机制。Flutter提供了三种类型的通道:

  1. MethodChannel:用于调用平台方法并接收返回值。
  2. EventChannel:用于接收来自平台的事件流。
  3. BasicMessageChannel:用于发送和接收字符串和半结构化信息。

MethodChannel

MethodChannel 主要用于 Flutter 应用和原生平台代码之间的双向通信。例如,Flutter 调用 iOS 方法或 iOS 调用 Flutter 方法。

Flutter 端代码

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

// 定义 MethodChannel
static const platform = const MethodChannel('com.example.flutter/native');

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

  print(batteryLevel);
}

iOS 端代码 (Objective-C)

objective-c 复制代码
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>

@interface AppDelegate : FlutterAppDelegate
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;
  FlutterMethodChannel* batteryChannel = [FlutterMethodChannel
                                          methodChannelWithName:@"com.example.flutter/native"
                                          binaryMessenger:controller];

  __weak typeof(self) weakSelf = self;
  [batteryChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
    if ([@"getBatteryLevel" isEqualToString:call.method]) {
      int batteryLevel = [weakSelf getBatteryLevel];

      if (batteryLevel == -1) {
        result([FlutterError errorWithCode:@"UNAVAILABLE"
                                   message:@"Battery info unavailable"
                                   details:nil]);
      } else {
        result(@(batteryLevel));
      }
    } else {
      result(FlutterMethodNotImplemented);
    }
  }];
  
  [super application:application didFinishLaunchingWithOptions:launchOptions];
  return YES;
}

- (int)getBatteryLevel {
  UIDevice* device = [UIDevice currentDevice];
  device.batteryMonitoringEnabled = YES;
  if (device.batteryState == UIDeviceBatteryStateUnknown) {
    return -1;
  } else {
    return (int)(device.batteryLevel * 100);
  }
}

@end

EventChannel

EventChannel 用于将事件流从平台传递到 Flutter。

Flutter 端代码

dart 复制代码
static const EventChannel eventChannel = EventChannel('com.example.flutter/charging');

@override
void initState() {
  super.initState();
  eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);
}

void _onEvent(Object event) {
  print('Charging status: $event');
}

void _onError(Object error) {
  print('Error occurred: $error');
}

iOS 端代码 (Objective-C)

objective-c 复制代码
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>

@interface AppDelegate : FlutterAppDelegate
@end

@implementation AppDelegate {
  FlutterEventSink _eventSink;
}

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;
  
  FlutterEventChannel* chargingChannel = [FlutterEventChannel
                                          eventChannelWithName:@"com.example.flutter/charging"
                                          binaryMessenger:controller];

  [chargingChannel setStreamHandler:self];
  
  [super application:application didFinishLaunchingWithOptions:launchOptions];
  return YES;
}

- (FlutterError*)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)events {
  _eventSink = events;
  [[UIDevice currentDevice] setBatteryMonitoringEnabled:YES];
  [self sendBatteryStateEvent];
  return nil;
}

- (FlutterError*)onCancelWithArguments:(id)arguments {
  _eventSink = nil;
  return nil;
}

- (void)sendBatteryStateEvent {
  UIDeviceBatteryState state = [[UIDevice currentDevice] batteryState];
  switch (state) {
    case UIDeviceBatteryStateCharging:
      _eventSink(@"charging");
      break;
    case UIDeviceBatteryStateUnplugged:
      _eventSink(@"discharging");
      break;
    default:
      _eventSink([FlutterError errorWithCode:@"UNAVAILABLE"
                                     message:@"Battery state unavailable"
                                     details:nil]);
      break;
  }
}

@end

BasicMessageChannel

BasicMessageChannel 用于发送和接收字符串和半结构化的信息(如JSON)。

Flutter 端代码

dart 复制代码
static const BasicMessageChannel<String> basicMessageChannel =
    BasicMessageChannel<String>('com.example.flutter/basic', StringCodec());

Future<void> sendMessage() async {
  try {
    String result = await basicMessageChannel.send('Hello from Flutter');
    print('Received response: $result');
  } catch (e) {
    print('Failed to send message: $e');
  }
}

iOS 端代码 (Objective-C)

objective-c 复制代码
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>

@interface AppDelegate : FlutterAppDelegate
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;
  FlutterBasicMessageChannel* messageChannel = [FlutterBasicMessageChannel
                                                messageChannelWithName:@"com.example.flutter/basic"
                                                binaryMessenger:controller];

  [messageChannel setMessageHandler:^(id message, FlutterReply reply) {
    NSLog(@"Received message from Flutter: %@", message);
    reply(@"Hello from iOS");
  }];
  
  [super application:application didFinishLaunchingWithOptions:launchOptions];
  return YES;
}

@end

这些通道类型在Flutter和iOS之间提供了灵活且强大的通信机制。通过使用这些通道,可以有效地构建跨平台应用,同时利用平台特定的功能和特性。

相关推荐
腾讯TNTWeb前端团队5 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰8 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪9 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪9 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy9 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom10 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom10 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom10 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom10 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom10 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试