DartNative:Dart与原生API之间的桥梁

DartNative:Dart与原生API之间的桥梁

DartNative 是一款高效通信工具,用于连接Dart和原生API,它将低效率的Flutter通道替换为更快、更简洁的代码。

DartNative Build Status Dart CI

功能亮点

动态同步与异步通道

DartNative 支持动态调用任何原生API,无论是同步还是异步,都能轻松应对。

多语言接口直接调用

不再需要像Flutter Channel那样的参数序列化和返回值处理,DartNative 提供了直接调用,实现了不同语言接口间的自动对象转换。

Dart最终器支持

即使你的环境低于Flutter 3(Dart 2.17),DartNative 也能在Dart Flutter 2.2.0(Dart 2.13.0)及更高版本中支持Dart最终器。

简洁的桥接代码生成

DartNative 自动类型转换功能使得其生成的桥接代码比Flutter通道更加简洁。

项目要求

不同的DartNative版本对应不同版本的Flutter和codegen,请参考下表:

| DartNative 版本 | Flutter 要求 | Codegen 版本 | | --- | --- | --- | | 0.4.x - 0.7.x | Flutter 2.2.0 (Dart 2.13.0) | 2.x | | 0.3.x | Flutter 1.20.0 (Dart 2.9.1) | 1.2.x | | 0.2.x | Flutter 1.12.13 (Dart 2.7) | 1.x |

支持平台

包括iOS、macOS和Android。

使用教程

基础用法:接口绑定

首先,在dependencies添加dart_native,在dev_dependencies中添加build_runner。然后你可以开始编写以下示例代码:

Dart 调用 Native

Dart 代码:

final interface = Interface("MyFirstInterface");
// 示例:字符串类型
String helloWorld() {
    return interface.invokeMethodSync('hello', args: ['world']);
}
// 示例:数字类型
Future<int> sum(int a, int b) {
    return interface.invokeMethod('sum', args: [a, b]);
}

对应的Objective-C代码:

@implementation DNInterfaceDemo

// 注册接口名称。
InterfaceEntry(MyFirstInterface)

// 注册方法 "hello"。
InterfaceMethod(hello, myHello:(NSString *)str) {
    return [NSString stringWithFormat:@"hello %@!", str];
}

// 注册方法 "sum"。
InterfaceMethod(sum, addA:(int32_t)a withB:(int32_t)b) {
    return @(a + b);
}

@end

对应的Java代码:


// 加载libdart_native.so
DartNativePlugin.loadSo();

@InterfaceEntry(name = "MyFirstInterface")
public class InterfaceDemo extends DartNativeInterface {

    @InterfaceMethod(name = "hello")
    public String hello(String str) {
        return "hello " + str;
    }

    @InterfaceMethod(name = "sum")
    public int sum(int a, int b) {
        return a + b;
    }
}

若动态库路径非默认,可采用dartNativeInitCustomSoPath()初始化,并传入特定路径。

Native 调用 Dart

Dart 代码:

interface.setMethodCallHandler('totalCost',
        (double unitCost, int count, List list) async {
    return {'totalCost: ${unitCost * count}': list};
});

对应的Objective-C代码:

[self invokeMethod:@"totalCost"
arguments:@[@0.123456789, @10, @[@"testArray"]]
result:^(id _Nullable result, NSError * _Nullable error) {
    NSLog(@"%@", result);
}];

对应的Java代码:

invokeMethod("totalCost", new Object[]{0.123456789, 10, Arrays.asList("hello", "world")},
new DartNativeResult() {
    @Override
    public void onResult(@Nullable Object result) {
        Map retMap = (Map) result;
        // 进行操作
    }

    @Override
    public void error(@Nullable String errorMessage) {
        // 错误处理
    }
});
Dart 最终器
final foo = Bar(); // 自定义实例
unitTest.addFinalizer(() { // 注册最终器回调
    print('The instance of \'foo\' has been destroyed!'); // 当 'foo' 被GC销毁时,此行会被执行。
});
数据类型支持

DartNative 支持多种数据类型,如null、bool、int、double、String、List、Map、Set以及Function等。具体详情见项目文档。

高级用法:动态调用方法

  1. 添加dart_native至依赖项,将build_runner加入开发依赖项。

  2. 使用@dartnative/codegen或手动编写Dart代码进行代码生成。

  3. 使用dart_native_gen创建自动类型转换代码(步骤3.1-3.3):

    • 3.1 在Dart包装类上注解@native
      @native
      class RuntimeSon extends RuntimeStub {
        RuntimeSon([Class isa]) : super(Class('RuntimeSon'));
        RuntimeSon.fromPointer(Pointer<Void> ptr) : super.fromPointer(ptr);
      }
      
    • 3.2 在你自己的入口(如main())上注解@nativeRoot
      @nativeRoot
      void main() {
        runApp(App());
      }
      
    • 3.3 运行以下命令以生成文件:
      flutter packages pub run build_runner build --delete-conflicting-outputs 
      
      首先建议运行clean命令:
      flutter packages pub run build_runner clean
      
  4. 在第3.3步中生成的<generated-name>.dn.dart文件中的函数名(由pubspec.yaml中的name决定)调用自动生成的函数。

    @nativeRoot
    void main() {
      // 函数名由 pubspec.yaml 的 name 生成。
      runDartNativeExample(); 
      runApp(App());
    }
    
  5. 根据生成的代码,可以继续编写iOS和Android相关的示例代码。

    • iOS 示例(查看/dart_native/example/lib/ios/unit_test.dart
    • Android 示例(查看/dart_native/example/lib/android/unit_test.dart

注意:如果你在macOS上使用dart_native,请确保在Podfile中使用use_frameworks!

文档资源

了解更多关于DartNative的信息:

常见问题

  • Q: macOS归档时出现 "Failed to lookup symbol (dlsym(RTLD_DEFAULT, InitDartApiDL): symbol not found)" 错误。 A: 选择其中一个解决方案:
      1. 使用动态库:在Podfile中添加use_frameworks!
      1. 选择目标Runner -> 构建设置 -> � rip Style -> 更改为“非全局符号”。

贡献说明

  • 如需帮助或想要提问,请开放问题。
  • 如果发现bug,请提交问题。
  • 对于特性请求,请开放问题。
  • 如果要贡献,提交拉取请求。

许可证

DartNative遵循BSD 3-Clause许可证。更多信息请参阅LICENSE文件。

尝试DartNative,体验快速、强大的原生API交互,让您的Dart开发工作更加高效!

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

任澄翊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值