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之间提供了灵活且强大的通信机制。通过使用这些通道,可以有效地构建跨平台应用,同时利用平台特定的功能和特性。

相关推荐
nppe62 分钟前
sequlize操作mysql小记
前端·后端
Moment11 分钟前
面试官:一个接口使用postman这些测试很快,但是页面加载很慢怎么回事 😤😤😤
前端·后端·面试
诗书画唱15 分钟前
【前端面试题】JavaScript 核心知识点解析(第二十二题到第六十一题)
开发语言·前端·javascript
excel21 分钟前
前端必备:从能力检测到 UA-CH,浏览器客户端检测的完整指南
前端
前端小巷子28 分钟前
Vue 3全面提速剖析
前端·vue.js·面试
悟空聊架构35 分钟前
我的网站被攻击了,被干掉了 120G 流量,还在持续攻击中...
java·前端·架构
CodeSheep36 分钟前
国内 IT 公司时薪排行榜。
前端·后端·程序员
尖椒土豆sss40 分钟前
踩坑vue项目中使用 iframe 嵌套子系统无法登录,不报错问题!
前端·vue.js
遗悲风41 分钟前
html二次作业
前端·html
江城开朗的豌豆44 分钟前
React输入框优化:如何精准获取用户输入完成后的最终值?
前端·javascript·全栈