flutter-native-interop by flutter/skills
npx skills add https://github.com/flutter/skills --skill flutter-native-interop将 Flutter 应用程序与 Android、iOS 和 Web 环境中的平台特定代码及原生功能集成。确定最佳的互操作性策略(FFI、平台通道、平台视图或 JS 互操作),并实现必要的 Dart 和原生代码绑定,同时遵循线程安全、WebAssembly(Wasm)兼容性和现代构建钩子标准。
使用以下决策树评估用户需求,以选择正确的集成路径:
dart:ffi 配合 package_ffi 模板和构建钩子。plugin_ffi 模板。MethodChannel)或 pigeon 包进行类型安全的代码生成。广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
AndroidView / AndroidViewSurface,iOS 使用 UiKitView)。package:web 和 dart:js_interop(Wasm 兼容)。使用 HtmlElementView 嵌入网页内容。请暂停并询问用户: "您目标平台是哪些?需要集成什么具体的原生功能或 UI 组件?"
dart:ffi)如果选择了场景 A,请使用构建钩子(Flutter 3.38+)实现现代 FFI 架构。
生成包:
flutter create --template=package_ffi native_add
配置构建钩子(hook/build.dart)以编译原生代码:
import 'package:hooks/hooks.dart';
import 'package:native_toolchain_c/native_toolchain_c.dart';
void main(List<String> args) async {
await build(args, (config, output) async {
final builder = CBuilder.library(
name: 'native_add',
assetId: 'native_add/src/native_add.dart',
sources: ['src/native_add.c'],
);
await builder.run(config: config, output: output);
});
}
在 Dart 中绑定原生函数(lib/src/native_add.dart):
import 'dart:ffi';
@Native<Int32 Function(Int32, Int32)>()
external int sum(int a, int b);
如果选择了场景 B,请实现异步消息传递。
Dart 客户端实现:
import 'package:flutter/services.dart';
class NativeApi {
static const platform = MethodChannel('com.example.app/channel');
Future<String> getNativeData() async {
try {
final String result = await platform.invokeMethod('getData');
return result;
} on PlatformException catch (e) {
return "Error: '${e.message}'.";
}
}
}
Android 宿主实现(Kotlin):
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
class MainActivity: FlutterActivity() {
private val CHANNEL = "com.example.app/channel"
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "getData") {
result.success("Data from Android")
} else {
result.notImplemented()
}
}
}
}
iOS 宿主实现(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 channel = FlutterMethodChannel(name: "com.example.app/channel", binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
if call.method == "getData" {
result("Data from iOS")
} else {
result(FlutterMethodNotImplemented)
}
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
如果选择了场景 C,请嵌入原生视图。
Dart 实现(iOS 示例):
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
Widget buildNativeView() {
const String viewType = '<platform-view-type>';
final Map<String, dynamic> creationParams = <String, dynamic>{};
return UiKitView(
viewType: viewType,
layoutDirection: TextDirection.ltr,
creationParams: creationParams,
creationParamsCodec: const StandardMessageCodec(),
);
}
iOS 工厂实现(Swift):
import Flutter
import UIKit
class FLNativeViewFactory: NSObject, FlutterPlatformViewFactory {
private var messenger: FlutterBinaryMessenger
init(messenger: FlutterBinaryMessenger) {
self.messenger = messenger
super.init()
}
func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
return FLNativeView(frame: frame, viewIdentifier: viewId, arguments: args, binaryMessenger: messenger)
}
public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
return FlutterStandardMessageCodec.sharedInstance()
}
}
class FLNativeView: NSObject, FlutterPlatformView {
private var _view: UIView
init(frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?, binaryMessenger messenger: FlutterBinaryMessenger?) {
_view = UIView()
super.init()
_view.backgroundColor = UIColor.blue
}
func view() -> UIView { return _view }
}
验证与修复: 确保工厂已在 AppDelegate.swift 中使用 registrar.register(factory, withId: "<platform-view-type>") 注册。
如果选择了场景 D,请实现 Wasm 兼容的 Web 集成。
JS 互操作(Dart):
import 'dart:js_interop';
import 'package:web/web.dart' as web;
@JS('console.log')
external void log(JSAny? value);
void manipulateDOM() {
final div = web.document.createElement('div') as web.HTMLDivElement;
div.text = "Hello from Wasm-compatible Dart!";
web.document.body?.append(div);
log("DOM updated".toJS);
}
嵌入 HTML 元素:
import 'package:flutter/widgets.dart';
import 'package:web/web.dart' as web;
Widget buildVideoElement() {
return HtmlElementView.fromTag('video', onElementCreated: (Object video) {
final videoElement = video as web.HTMLVideoElement;
videoElement.src = 'https://example.com/video.mp4';
videoElement.style.width = '100%';
videoElement.style.height = '100%';
});
}
Handler(Looper.getMainLooper()).post(Android)或 DispatchQueue.main.async(iOS)。dart:html、dart:js 或 package:js。您必须使用 package:web 和 dart:js_interop 以确保应用程序能编译为 Wasm。build.dart 钩子时,动态库在所有目标架构中必须具有一致的文件名(例如,不要使用 lib_arm64.dylib)。SurfaceView 存在问题,应尽可能避免。为了获得更好的 Flutter 渲染性能,建议使用 TextureLayerHybridComposition。每周安装量
947
代码仓库
GitHub 星标数
784
首次出现
2026年3月4日
安全审计
安装于
codex913
cursor911
github-copilot910
gemini-cli909
opencode909
kimi-cli908
Integrates Flutter applications with platform-specific code and native features across Android, iOS, and Web environments. Determines the optimal interoperability strategy (FFI, Platform Channels, Platform Views, or JS Interop) and implements the necessary Dart and native code bindings while adhering to thread safety, WebAssembly (Wasm) compatibility, and modern build hook standards.
Evaluate the user's requirements using the following decision tree to select the correct integration path:
dart:ffi with the package_ffi template and build hooks.plugin_ffi template.MethodChannel) or the pigeon package for type-safe code generation.AndroidView / AndroidViewSurface for Android, UiKitView for iOS).package:web and dart:js_interop (Wasm-compatible). Use HtmlElementView for embedding web content.STOP AND ASK THE USER: "Which platform(s) are you targeting, and what specific native functionality or UI component do you need to integrate?"
dart:ffi)If Scenario A is selected, implement the modern FFI architecture using build hooks (Flutter 3.38+).
Generate the package:
flutter create --template=package_ffi native_add
Configure the build hook (hook/build.dart) to compile the native code:
import 'package:hooks/hooks.dart';
import 'package:native_toolchain_c/native_toolchain_c.dart';
void main(List<String> args) async {
await build(args, (config, output) async {
final builder = CBuilder.library(
name: 'native_add',
assetId: 'native_add/src/native_add.dart',
sources: ['src/native_add.c'],
);
await builder.run(config: config, output: output);
});
}
Bind the native function in Dart (lib/src/native_add.dart):
import 'dart:ffi';
@Native<Int32 Function(Int32, Int32)>()
external int sum(int a, int b);
If Scenario B is selected, implement asynchronous message passing.
Dart Client Implementation:
import 'package:flutter/services.dart';
class NativeApi {
static const platform = MethodChannel('com.example.app/channel');
Future<String> getNativeData() async {
try {
final String result = await platform.invokeMethod('getData');
return result;
} on PlatformException catch (e) {
return "Error: '${e.message}'.";
}
}
}
Android Host Implementation (Kotlin):
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
class MainActivity: FlutterActivity() {
private val CHANNEL = "com.example.app/channel"
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "getData") {
result.success("Data from Android")
} else {
result.notImplemented()
}
}
}
}
iOS Host Implementation (Swift):
If Scenario C is selected, embed native views.
Dart Implementation (iOS Example):
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
Widget buildNativeView() {
const String viewType = '<platform-view-type>';
final Map<String, dynamic> creationParams = <String, dynamic>{};
return UiKitView(
viewType: viewType,
layoutDirection: TextDirection.ltr,
creationParams: creationParams,
creationParamsCodec: const StandardMessageCodec(),
);
}
iOS Factory Implementation (Swift):
import Flutter
import UIKit
class FLNativeViewFactory: NSObject, FlutterPlatformViewFactory {
private var messenger: FlutterBinaryMessenger
init(messenger: FlutterBinaryMessenger) {
self.messenger = messenger
super.init()
}
func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
return FLNativeView(frame: frame, viewIdentifier: viewId, arguments: args, binaryMessenger: messenger)
}
public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
return FlutterStandardMessageCodec.sharedInstance()
}
}
class FLNativeView: NSObject, FlutterPlatformView {
private var _view: UIView
init(frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?, binaryMessenger messenger: FlutterBinaryMessenger?) {
_view = UIView()
super.init()
_view.backgroundColor = UIColor.blue
}
func view() -> UIView { return _view }
}
Validate-and-Fix: Ensure the factory is registered in AppDelegate.swift using registrar.register(factory, withId: "<platform-view-type>").
If Scenario D is selected, implement Wasm-compatible web integrations.
JS Interop (Dart):
import 'dart:js_interop';
import 'package:web/web.dart' as web;
@JS('console.log')
external void log(JSAny? value);
void manipulateDOM() {
final div = web.document.createElement('div') as web.HTMLDivElement;
div.text = "Hello from Wasm-compatible Dart!";
web.document.body?.append(div);
log("DOM updated".toJS);
}
Embedding HTML Elements:
import 'package:flutter/widgets.dart';
import 'package:web/web.dart' as web;
Widget buildVideoElement() {
return HtmlElementView.fromTag('video', onElementCreated: (Object video) {
final videoElement = video as web.HTMLVideoElement;
videoElement.src = 'https://example.com/video.mp4';
videoElement.style.width = '100%';
videoElement.style.height = '100%';
});
}
Handler(Looper.getMainLooper()).post (Android) or DispatchQueue.main.async (iOS) if jumping from a background thread.dart:html, dart:js, or package:js. You MUST use package:web and dart:js_interop to ensure the app compiles to Wasm.build.dart hooks for Apple platforms, dynamic libraries MUST have consistent filenames across all target architectures (e.g., do not use ).Weekly Installs
947
Repository
GitHub Stars
784
First Seen
Mar 4, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
codex913
cursor911
github-copilot910
gemini-cli909
opencode909
kimi-cli908
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
102,200 周安装
Gemini Interactions API 指南:统一接口、智能体交互与服务器端状态管理
833 周安装
Apollo MCP 服务器:让AI代理通过GraphQL API交互的完整指南
834 周安装
智能体记忆系统构建指南:分块策略、向量存储与检索优化
835 周安装
Scrapling官方网络爬虫框架 - 自适应解析、绕过Cloudflare、Python爬虫库
836 周安装
抽奖赢家选取器 - 随机选择工具,支持CSV、Excel、Google Sheets,公平透明
838 周安装
Medusa 前端开发指南:使用 SDK、React Query 构建电商商店
839 周安装
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 channel = FlutterMethodChannel(name: "com.example.app/channel", binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
if call.method == "getData" {
result("Data from iOS")
} else {
result(FlutterMethodNotImplemented)
}
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
lib_arm64.dylibSurfaceView on Android via Platform Views is problematic and should be avoided when possible. Prefer TextureLayerHybridComposition for better Flutter rendering performance.