flutter-interoperating-with-native-apis

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Integrating Platform-Specific Code in Flutter

在Flutter中集成平台专属代码

Contents

目录

Core Concepts & Terminology

核心概念与术语

  • FFI (Foreign Function Interface): The
    dart:ffi
    library used to bind Dart directly to native C/C++ APIs.
  • Platform Channel: The asynchronous message-passing system (
    MethodChannel
    ,
    BasicMessageChannel
    ) connecting the Dart client (UI) to the host platform (Kotlin/Java, Swift/Objective-C, C++).
  • Pigeon: A code-generation tool that creates type-safe Platform Channels.
  • Platform View: A mechanism to embed native UI components (e.g., Android
    View
    , iOS
    UIView
    ) directly into the Flutter widget tree.
  • JS Interop: The modern, Wasm-compatible approach to interacting with JavaScript and DOM APIs using
    package:web
    and
    dart:js_interop
    .
  • FFI (Foreign Function Interface):
    dart:ffi
    库,用于将Dart直接绑定到原生C/C++ API。
  • Platform Channel: 异步消息传递系统(
    MethodChannel
    BasicMessageChannel
    ),连接Dart客户端(UI)与宿主平台(Kotlin/Java、Swift/Objective-C、C++)。
  • Pigeon: 一种代码生成工具,用于创建类型安全的Platform Channel。
  • Platform View: 一种将原生UI组件(如Android
    View
    、iOS
    UIView
    )直接嵌入Flutter组件树的机制。
  • JS Interop: 兼容Wasm的现代交互方式,通过
    package:web
    dart:js_interop
    与JavaScript及DOM API交互。

Binding to Native C/C++ Code (FFI)

绑定原生C/C++代码(FFI)

Use FFI to execute high-performance native code or utilize existing C/C++ libraries without the overhead of asynchronous Platform Channels.
当需要执行高性能原生代码,或使用现有C/C++库且不想承担异步Platform Channel的开销时,可使用FFI。

Project Setup

项目设置

  • If creating a standard C/C++ integration (Recommended since Flutter 3.38): Use the
    package_ffi
    template. This utilizes
    build.dart
    hooks to compile native code, eliminating the need for OS-specific build files (CMake, build.gradle, podspec).
    bash
    flutter create --template=package_ffi <package_name>
  • If requiring access to the Flutter Plugin API or Play Services: Use the legacy
    plugin_ffi
    template.
    bash
    flutter create --template=plugin_ffi <plugin_name>
  • 若创建标准C/C++集成(Flutter 3.38及以上版本推荐): 使用
    package_ffi
    模板。该模板利用
    build.dart
    钩子编译原生代码,无需OS专属构建文件(CMake、build.gradle、podspec)。
    bash
    flutter create --template=package_ffi <package_name>
  • 若需要访问Flutter Plugin API或Play Services: 使用旧版
    plugin_ffi
    模板。
    bash
    flutter create --template=plugin_ffi <plugin_name>

Implementation Rules

实现规则

  • Symbol Visibility: Always mark C++ symbols with
    extern "C"
    and prevent linker discarding during link-time optimization (LTO).
    cpp
    extern "C" __attribute__((visibility("default"))) __attribute__((used))
  • Dynamic Library Naming (Apple Platforms): Ensure your
    build.dart
    hook produces the exact same filename across all target architectures (e.g.,
    arm64
    vs
    x86_64
    ) and SDKs (
    iphoneos
    vs
    iphonesimulator
    ). Do not append architecture suffixes to the
    .dylib
    or
    .framework
    names.
  • Binding Generation: Always use
    package:ffigen
    to generate Dart bindings from your C headers (
    .h
    ). Configure this in
    ffigen.yaml
    .
  • 符号可见性: 务必用
    extern "C"
    标记C++符号,并在链接时优化(LTO)过程中防止链接器丢弃符号。
    cpp
    extern "C" __attribute__((visibility("default"))) __attribute__((used))
  • 动态库命名(Apple平台): 确保
    build.dart
    钩子在所有目标架构(如
    arm64
    x86_64
    )及SDK(
    iphoneos
    iphonesimulator
    )下生成完全相同的文件名。不要在
    .dylib
    .framework
    名称后添加架构后缀。
  • 绑定生成: 务必使用
    package:ffigen
    从C头文件(
    .h
    )生成Dart绑定。在
    ffigen.yaml
    中进行配置。

Implementing Platform Channels & Pigeon

实现Platform Channel与Pigeon

Use Platform Channels when you need to interact with platform-specific APIs (e.g., Battery, Bluetooth, OS-level services) using the platform's native language.
当需要使用平台原生语言调用平台专属API(如电池、蓝牙、系统级服务)时,可使用Platform Channel。

Pigeon (Type-Safe Channels)

Pigeon(类型安全Channel)

Always prefer
package:pigeon
over raw
MethodChannel
implementations for complex or frequently used APIs.
  1. Define the messaging protocol in a standalone Dart file using Pigeon annotations (
    @HostApi()
    ).
  2. Generate the host (Kotlin/Swift/C++) and client (Dart) code.
  3. Implement the generated interfaces on the native side.
对于复杂或频繁使用的API,务必优先使用
package:pigeon
而非原生
MethodChannel
实现。
  1. 在独立Dart文件中使用Pigeon注解(
    @HostApi()
    )定义消息协议。
  2. 生成宿主端(Kotlin/Swift/C++)与客户端(Dart)代码。
  3. 在原生端实现生成的接口。

Threading Rules

线程规则

  • Main Thread Requirement: Always invoke channel methods destined for Flutter on the platform's main thread (UI thread).
  • Background Execution: If executing channel handlers on a background thread (Android/iOS), you must use the Task Queue API (
    makeBackgroundTaskQueue()
    ).
  • Isolates: To use plugins/channels from a Dart background
    Isolate
    , ensure it is registered using
    BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken)
    .
  • 主线程要求: 调用目标为Flutter的Channel方法时,务必在平台主线程(UI线程)执行。
  • 后台执行: 若在后台线程(Android/iOS)执行Channel处理器,必须使用任务队列API(
    makeBackgroundTaskQueue()
    )。
  • Isolate: 若要在Dart后台
    Isolate
    中使用插件/Channel,需确保通过
    BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken)
    完成注册。

Hosting Native Platform Views

托管原生平台视图

Use Platform Views to embed native UI components (e.g., Google Maps, native video players) into the Flutter widget tree.
当需要将原生UI组件(如谷歌地图、原生视频播放器)嵌入Flutter组件树时,可使用Platform View。

Android Platform Views

Android平台视图

Evaluate the trade-offs between the two rendering modes and select the appropriate one:
  • If requiring perfect fidelity, accessibility, or SurfaceView support: Use Hybrid Composition (
    PlatformViewLink
    +
    AndroidViewSurface
    ). This appends the native view to the hierarchy but may reduce Flutter's rendering performance.
  • If prioritizing Flutter rendering performance and transformations: Use Texture Layer (
    AndroidView
    ). This renders the native view into a texture. Note: Quick scrolling may drop frames, and
    SurfaceView
    is problematic.
评估两种渲染模式的利弊,选择合适的模式:
  • 若需要完美的保真度、无障碍支持或SurfaceView支持: 使用Hybrid Composition
    PlatformViewLink
    +
    AndroidViewSurface
    )。它会将原生视图添加到层级结构中,但可能会降低Flutter的渲染性能。
  • 若优先考虑Flutter的渲染性能和变换效果: 使用Texture Layer
    AndroidView
    )。它会将原生视图渲染为纹理。注意:快速滚动可能会丢帧,且
    SurfaceView
    存在兼容性问题。

iOS Platform Views

iOS平台视图

  • iOS exclusively uses Hybrid Composition.
  • Implement
    FlutterPlatformViewFactory
    and
    FlutterPlatformView
    in Swift or Objective-C.
  • Use the
    UiKitView
    widget on the Dart side.
  • Limitation:
    ShaderMask
    and
    ColorFiltered
    widgets cannot be applied to iOS Platform Views.
  • iOS仅支持Hybrid Composition。
  • 在Swift或Objective-C中实现
    FlutterPlatformViewFactory
    FlutterPlatformView
  • 在Dart端使用
    UiKitView
    组件。
  • 限制:
    ShaderMask
    ColorFiltered
    组件无法应用于iOS Platform View。

Integrating Web Content & Wasm

集成Web内容与Wasm

Flutter Web supports compiling to WebAssembly (Wasm) for improved performance and multi-threading.
Flutter Web支持编译为WebAssembly(Wasm)以提升性能并实现多线程。

Wasm Compilation

Wasm编译

  • Compile to Wasm using:
    flutter build web --wasm
    .
  • Server Configuration: To enable multi-threading, configure your HTTP server to emit the following headers:
    • Cross-Origin-Embedder-Policy: credentialless
      (or
      require-corp
      )
    • Cross-Origin-Opener-Policy: same-origin
  • Limitation: WasmGC is not currently supported on iOS browsers (WebKit limitation). Flutter will automatically fall back to JavaScript if WasmGC is unavailable.
  • 使用以下命令编译为Wasm:
    flutter build web --wasm
  • 服务器配置: 若要启用多线程,需配置HTTP服务器发送以下响应头:
    • Cross-Origin-Embedder-Policy: credentialless
      (或
      require-corp
    • Cross-Origin-Opener-Policy: same-origin
  • 限制: iOS浏览器(WebKit)目前不支持WasmGC。若WasmGC不可用,Flutter会自动回退到JavaScript。

Web Interop

Web互操作

  • If writing new web-specific code: Strictly use
    package:web
    and
    dart:js_interop
    .
  • Do NOT use:
    dart:html
    ,
    dart:js
    , or
    package:js
    . These are incompatible with Wasm compilation.
  • Embedding HTML: Use
    HtmlElementView.fromTagName
    to inject arbitrary HTML elements (like
    <video>
    ) into the Flutter Web DOM.

  • 若编写新的Web专属代码: 严格使用
    package:web
    dart:js_interop
  • 禁止使用:
    dart:html
    dart:js
    package:js
    。这些库与Wasm编译不兼容。
  • 嵌入HTML: 使用
    HtmlElementView.fromTagName
    将任意HTML元素(如
    <video>
    )注入Flutter Web的DOM中。

Workflows

工作流程

Workflow: Creating a Native FFI Integration

工作流程:创建原生FFI集成

Use this workflow when binding to a C/C++ library.
  • Task Progress:
    • 1. Run
      flutter create --template=package_ffi <name>
      .
    • 2. Place C/C++ source code in the
      src/
      directory.
    • 3. Ensure all exported C++ functions are wrapped in
      extern "C"
      and visibility attributes.
    • 4. Configure
      ffigen.yaml
      to point to your header files.
    • 5. Run
      dart run ffigen
      to generate Dart bindings.
    • 6. Modify
      hook/build.dart
      if linking against pre-compiled or system libraries.
    • 7. Run validator ->
      flutter test
      -> review errors -> fix.
当绑定到C/C++库时,使用此工作流程。
  • 任务进度:
    • 1. 运行
      flutter create --template=package_ffi <name>
    • 2. 将C/C++源代码放入
      src/
      目录。
    • 3. 确保所有导出的C++函数都用
      extern "C"
      和可见性属性包裹。
    • 4. 配置
      ffigen.yaml
      指向你的头文件。
    • 5. 运行
      dart run ffigen
      生成Dart绑定。
    • 6. 若链接预编译或系统库,修改
      hook/build.dart
    • 7. 运行验证器 ->
      flutter test
      -> 查看错误 -> 修复问题。

Workflow: Implementing a Type-Safe Platform Channel (Pigeon)

工作流程:实现类型安全的Platform Channel(Pigeon)

Use this workflow when you need to call Kotlin/Swift APIs from Dart.
  • Task Progress:
    • 1. Add
      pigeon
      to
      dev_dependencies
      .
    • 2. Create
      pigeons/messages.dart
      and define data classes and
      @HostApi()
      abstract classes.
    • 3. Run the Pigeon generator script to output Dart, Kotlin, and Swift files.
    • 4. Android: Implement the generated interface in
      MainActivity.kt
      or your Plugin class.
    • 5. iOS: Implement the generated protocol in
      AppDelegate.swift
      or your Plugin class.
    • 6. Dart: Import the generated Dart file and call the API methods.
    • 7. Run validator -> verify cross-platform compilation -> review errors -> fix.
当需要从Dart调用Kotlin/Swift API时,使用此工作流程。
  • 任务进度:
    • 1. 在
      dev_dependencies
      中添加
      pigeon
    • 2. 创建
      pigeons/messages.dart
      ,定义数据类和
      @HostApi()
      抽象类。
    • 3. 运行Pigeon生成脚本,输出Dart、Kotlin和Swift文件。
    • 4. Android:
      MainActivity.kt
      或你的Plugin类中实现生成的接口。
    • 5. iOS:
      AppDelegate.swift
      或你的Plugin类中实现生成的协议。
    • 6. Dart: 导入生成的Dart文件并调用API方法。
    • 7. 运行验证器 -> 验证跨平台编译 -> 查看错误 -> 修复问题。

Workflow: Embedding a Native Platform View

工作流程:嵌入原生平台视图

Use this workflow when embedding a native UI component (e.g., a native map or camera view).
  • Task Progress:
    • 1. Dart: Create a widget that conditionally returns
      AndroidView
      (or
      PlatformViewLink
      ) for Android, and
      UiKitView
      for iOS based on
      defaultTargetPlatform
      .
    • 2. Android: Create a class implementing
      PlatformView
      that returns the native Android
      View
      .
    • 3. Android: Create a
      PlatformViewFactory
      and register it in
      configureFlutterEngine
      .
    • 4. iOS: Create a class implementing
      FlutterPlatformView
      that returns the native
      UIView
      .
    • 5. iOS: Create a
      FlutterPlatformViewFactory
      and register it in
      application:didFinishLaunchingWithOptions:
      .
    • 6. Run validator -> test on physical Android and iOS devices -> review UI clipping/scrolling issues -> fix.
当需要嵌入原生UI组件(如原生地图或相机视图)时,使用此工作流程。
  • 任务进度:
    • 1. Dart: 创建一个组件,根据
      defaultTargetPlatform
      为Android返回
      AndroidView
      (或
      PlatformViewLink
      ),为iOS返回
      UiKitView
    • 2. Android: 创建实现
      PlatformView
      的类,返回原生Android
      View
    • 3. Android: 创建
      PlatformViewFactory
      并在
      configureFlutterEngine
      中注册。
    • 4. iOS: 创建实现
      FlutterPlatformView
      的类,返回原生
      UIView
    • 5. iOS: 创建
      FlutterPlatformViewFactory
      并在
      application:didFinishLaunchingWithOptions:
      中注册。
    • 6. 运行验证器 -> 在Android和iOS真机上测试 -> 查看UI裁剪/滚动问题 -> 修复问题。