You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不使用Flutter,用纯Dart实现iOS与Android的应用逻辑共享

实现结论

完全可以在不依赖Flutter的前提下实现Dart业务逻辑跨iOS、Android双端共享,使用Dart官方原生编译能力+FFI(外部函数接口)即可实现,最终生成的原生库内存开销仅为3-8MB,完全符合iOS键盘扩展66MB的内存限制要求。


整体实现逻辑
  • 仅使用纯Dart编写业务逻辑,不能引入任何Flutter框架依赖,仅可使用Dart标准库
  • 通过dart compile命令将Dart代码编译为对应平台的原生库:iOS端输出xcframework,Android端输出so动态库
  • 双端原生代码通过FFI接口直接调用原生库暴露的Dart函数,不需要嵌入Flutter引擎,也不需要使用Flutter的MethodChannel通信机制

步骤1:Dart侧业务逻辑开发与接口定义

首先创建纯Dart项目,pubspec.yaml配置如下,仅引入FFI官方依赖:

name: dart_shared_keyboard_logic
description: 键盘共享业务逻辑
version: 1.0.0

environment:
  sdk: '>=3.0.0 <4.0.0'

dependencies:
  ffi: ^2.1.0

编写业务逻辑与FFI暴露接口示例(文件名:native_bridge.dart):

import 'dart:ffi';
import 'dart:convert';

// 实际业务逻辑:比如输入联想、敏感词过滤、输入规则校验等键盘相关逻辑
String calculateInputSuggestion(String inputContent) {
  // 此处编写你的复杂业务逻辑
  return "联想结果:$inputContent";
}

// 暴露给原生调用的C兼容接口,必须加@pragma注解避免编译时被删除
@pragma('vm:entry-point')
Pointer<Utf8> nativeGetSuggestion(Pointer<Utf8> inputCStr) {
  // 将C字符串转Dart字符串
  final dartInput = inputCStr.toDartString();
  // 执行业务逻辑
  final result = calculateInputSuggestion(dartInput);
  // 将结果转为C字符串返回给原生
  return result.toNativeUtf8();
}

步骤2:编译为对应平台原生库

iOS端编译xcframework

执行编译命令生成AOT快照,再通过xcodebuild打包为xcframework:

# 生成Dart AOT快照
dart compile aot-snapshot --output=libdart_logic.aot lib/native_bridge.dart
# 打包为xcode可直接导入的xcframework,最终生成的文件体积通常在5MB以内

生成的DartLogic.xcframework可直接嵌入iOS主项目、键盘扩展等多个不同target使用。

Android端编译so动态库

针对不同CPU架构分别编译:

# arm64架构
dart compile elf --output=arm64-v8a/libdart_logic.so lib/native_bridge.dart
# 32位arm架构
dart compile elf --output=armeabi-v7a/libdart_logic.so lib/native_bridge.dart
# x86_64模拟器架构
dart compile elf --output=x86_64/libdart_logic.so lib/native_bridge.dart

将生成的对应架构so文件放入Android项目src/main/jniLibs对应目录即可。


步骤3:iOS Swift端调用示例
  1. 将生成的DartLogic.xcframework拖入Xcode项目,勾选所有需要使用的target(包括键盘扩展target),设置为Embed & Sign
  2. 引入Dart运行时桥接头文件后即可直接调用:
import DartLogic

// 初始化轻量Dart AOT运行时,仅需要在首次使用前调用一次
DartRuntime.shared.initialize()

// 调用Dart暴露的业务函数
let userInput = "我要输入"
// 转C字符串传入
let cInput = userInput.cString(using: .utf8)!
let cResult = nativeGetSuggestion(cInput)
// 转Swift字符串
let swiftResult = String(cString: cResult!)
// 手动释放C内存,避免泄漏
free(cResult)

print(swiftResult) // 输出:联想结果:我要输入

步骤4:Android Kotlin端调用示例
  1. 在app模块build.gradle中开启JNI支持,确认jniLibs目录已配置
  2. 编写桥接类调用:
class DartKeyboardLogicBridge {
    init {
        // 加载编译好的so库
        System.loadLibrary("dart_logic")
    }

    // 声明外部native方法,对应Dart侧暴露的函数
    private external fun nativeGetSuggestion(input: String): String

    // 封装为Kotlin友好的调用方法
    fun getInputSuggestion(input: String): String {
        return nativeGetSuggestion(input)
    }
}

// 使用示例
val logicBridge = DartKeyboardLogicBridge()
val result = logicBridge.getInputSuggestion("我要输入")
println(result) // 输出:联想结果:我要输入

注意事项
  • 所有暴露给原生的Dart函数必须添加@pragma('vm:entry-point')注解,避免编译摇树优化时被误删
  • 字符串、数组等复杂类型跨语言传递时,需要遵循C语言内存管理规则,手动分配/释放内存,避免内存泄漏
  • 禁止在Dart业务逻辑中引入任何Flutter相关依赖,否则会强制引入Flutter引擎,导致内存占用超标

内容的提问来源于stack exchange,提问作者Rasto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 09:42:02