Getting Started with DartNative: A Guide for Developers

Sep 7, 2021 | Programming

DartNative serves as a powerful bridge connecting Dart to native APIs, efficiently replacing the low-performing Flutter channels with swift and concise code. Whether you’re developing an iOS, macOS, or Android application, DartNative has you covered with its dynamic capabilities.

Key Features of DartNative

  • Dynamic Synchronous & Asynchronous Channeling: DartNative enables seamless calls to any native API, supporting both synchronous and asynchronous operations.
  • Direct Multi-Language Interface Calls: Unlike Flutter channels, it eliminates the need for serialization of parameters and return values, offering direct calls and automatic object marshalling.
  • Dart Finalizer Support: Even if you’re using previous versions of Flutter, DartNative allows the use of Dart finalizers.
  • Auto-Generated Bridging Code: With automatic type conversion, DartNative minimizes the length and complexity of bridging code compared to Flutter channels.

Getting Started: Basic Usage

To start working with DartNative, begin by adding it to your project dependencies along with build_runner in your dev_dependencies. Below is a simple example of how Dart communicates with native APIs:

1. Setting Up Dart to Call Native APIs

Use the following code to call a native interface method:

dart
final interface = Interface(MyFirstInterface);

// Example for string type.
String helloWorld() {
    return interface.invokeMethodSync(hello, args: ['world']);
}

// Example for num type.
Future sum(int a, int b) async {
    return interface.invokeMethod('sum', args: [a, b]);
}

In this analogy, think of Dart as a friendly librarian that communicates with various rooms (native code). When you ask for a book (method), the librarian can directly retrieve or summon it, without waiting for any complicated procedures (serialization)—making the process seamless and efficient.

2. Corresponding Native Code

For iOS, your Objective-C implementation would look like this:

objectivec
@implementation DNInterfaceDemo
// Register interface name.
InterfaceEntry(MyFirstInterface) 
// Register method hello.
InterfaceMethod(hello, myHello:(NSString *)str) {
    return [NSString stringWithFormat:@"hello %@!", str];
}
// Register method sum.
InterfaceMethod(sum, addA:(int32_t)a withB:(int32_t)b) {
    return @(a + b);
}
@end

And for Android, the Java implementation would be:

java
load 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;
    }
}

Advanced Usage: Invoke Methods Dynamically

Once you are comfortable calling methods, you can extend your DartNative experience by invoking methods dynamically:

  1. Add DartNative to dependencies and Build_runner to dev_dependencies.
  2. Generate Dart wrapper code using @dartnativecodegen or manually write Dart code.
  3. Generate code for automatic type conversion using dart_native_gen.
  4. Implement the generated functions in your main application. Utilize the auto-generated binding code for seamless integration.

Troubleshooting Common Issues

In case you run into any issues, here are some troubleshooting tips:

  • Failed to lookup symbol (dlsym(RTLD_DEFAULT, InitDartApiDL): symbol not found): This error often indicates a configuration issue. Solutions include:
    • Use a dynamic library by adding use_frameworks! in your Podfile.
    • Adjust your Target Runner’s Build Settings to switch the Strip Style from All Symbols to Non-Global Symbols.
  • If you encounter problems with method calls, ensure you have properly registered all your methods in native APIs.

For more insights, updates, or to collaborate on AI development projects, stay connected with fxis.ai.

Conclusion

With DartNative, the complexity of bridging Dart to native APIs is drastically reduced, providing a clean and efficient way to harness the capabilities of native languages within your Flutter applications.

At fxis.ai, we believe that such advancements are crucial for the future of AI, as they enable more comprehensive and effective solutions. Our team is continually exploring new methodologies to push the envelope in artificial intelligence, ensuring that our clients benefit from the latest technological innovations.

Stay Informed with the Newest F(x) Insights and Blogs

Tech News and Blog Highlights, Straight to Your Inbox