Unify: A Framework for Efficient Flutter‑Native Hybrid Communication in Mobile Development
Unify is a Didi‑developed framework that lets developers declare Flutter‑native modules with Dart annotations, automatically generates matching Android, iOS and Flutter code, and streamlines large‑scale bidirectional communication, eliminating manual channel errors while enabling batch export of dozens of SDKs and boosting cross‑platform development efficiency.
Introduction
In the mobile development field, cross‑platform technologies have become a trend due to their efficiency gains. Flutter, a popular cross‑platform framework, is known for high performance, self‑rendering, and broad applicability. It is extensively used in Didi’s international business, such as the international food‑delivery and ride‑hailing driver apps, achieving more than 50% delivery efficiency improvement.
When Flutter and native code coexist at large scale, bidirectional communication between existing native services and new Flutter services becomes a pain point.
Background
During cross‑platform rollout, native implementations are often retained and gradually replaced by Flutter. This leads to several practical problems:
How to efficiently import a large number of native SDKs into Flutter?
How to efficiently import many business features into Flutter?
How to export Flutter modules back to native?
These issues are collectively referred to as hybrid communication problems .
Flutter’s official Channel solution suffers from several shortcomings in large‑scale scenarios, such as manual parameter parsing errors, difficulty maintaining massive export code, and cumbersome API wrapping.
Pigeon, a Google‑provided solution based on code generation, improves quality and reduces integration cost, but still leaves room for efficiency gains when exporting many modules.
Unify Overview
Unify, developed by Didi International Food‑Delivery team, addresses the above challenges. Its key features include:
Platform‑agnostic module abstraction : Developers declare module interfaces and entities in Dart, independent of the underlying platform.
Flexible implementation injection : Implementations can be injected on Android, iOS, or Flutter side.
Automatic code generation : A powerful generator produces unified SDKs for Flutter, Android, and iOS.
Using Unify, Didi has successfully imported over 16 native platform capabilities and 26 business capabilities into Flutter, establishing two architectural patterns – UniFoundation and UniBusiness – that support end‑to‑end cross‑platform deployment.
Core Concepts
Typical hybrid communication scenarios include:
Exporting native modules to Flutter.
Exporting Flutter modules to native.
Transferring complex entity classes across the interface.
Unify defines three core annotations: UniNativeModule: Declares a module whose implementation is provided by native code. UniFlutterModule: Declares a module whose implementation is provided by Flutter. UniModel: Declares a cross‑platform data model that can be serialized and transferred transparently.
Getting Started
The following example demonstrates how to import a native system‑information SDK into Flutter using Unify.
Step 1: Module Declaration
Create an interface directory in the Flutter project root and add two Dart abstract classes.
<span>// device_info_service.dart</span></code><code><span>@UniNativeModule()</span></code><code><span>abstract class DeviceInfoService {</span></code><code><span> /// Get device information</span></code><code><span> Future<DeviceInfoModel> getDeviceInfo();</span></code><code><span>}</span>Declare the data model:
<span>// device_info_model.dart</span></code><code><span>@UniModel()</span></code><code><span>class DeviceInfoModel {</span></code><code><span> String? osVersion;</span></code><code><span> String? memory;</span></code><code><span> String? platform;</span></code><code><span>}</span>Step 2: Run Unify Generator
Execute the following command to generate cross‑platform code:
<span>flutter pub run unify api\</span></code><code><span> --input=`pwd`/interface \</span></code><code><span> --dart_out=`pwd`/lib \</span></code><code><span> --java_out=`pwd`/android/src/main/java/com/example/uninativemodule_demo \</span></code><code><span> --java_package=com.example.uninativemodule_demo \</span></code><code><span> --oc_out=`pwd`/ios/Classes \</span></code><code><span> --dart_null_safety=true \</span></code><code><span> --uniapi_prefix=UD</span>The generator creates:
Implementation injection interfaces for Android (Java) and iOS (Objective‑C).
Unified calling interfaces for all three platforms (Flutter, Android, iOS).
Step 3: Implement Native Side
Android implementation:
<span>public class DeviceInfoServiceImpl implements DeviceInfoService {</span></code><code><span> @Override</span></code><code><span> public void getDeviceInfo(Result<DeviceInfoModel> result) {</span></code><code><span> DeviceInfoModel model = new DeviceInfoModel();</span></code><code><span> // ... fill model fields ...</span></code><code><span> result.success(model);</span></code><code><span> }</span></code><code><span>}</span>iOS implementation:
<span>// DeviceInfoServiceVendor.h</span></code><code><span>@interface DeviceInfoServiceVendor : NSObject<DeviceInfoService></span></code><code><span>@end</span></code><code><span>// DeviceInfoServiceVendor.m</span></code><code><span>@implementation DeviceInfoServiceVendor</span></code><code><span>UNI_EXPORT(DeviceInfoServiceVendor)</span></code><code><span>- (void)getDeviceInfo:(void(^)(DeviceInfoModel* result))success fail:(void(^)(FlutterError* error))fail {</span></code><code><span> DeviceInfoModel *model = [DeviceInfoModel new];</span></code><code><span> // ... fill model fields ...</span></code><code><span> success(model);</span></code><code><span>}</span></code><code><span>@end</span>Step 4: Call from Flutter
After the native side is registered, the module can be invoked in Flutter just like any ordinary Flutter API:
<span>OutlinedButton(</span></code><code><span> child: const Text("Get Device Info"),</span></code><code><span> onPressed: () {</span></code><code><span> DeviceInfoService.getDeviceInfo().then((deviceInfoModel) {</span></code><code><span> setState(() {</span></code><code><span> _platformVersion = "
${deviceInfoModel.encode()}";</span></code><code><span> });</span></code><code><span> });</span></code><code><span> },</span></code><code><span>),</span>The result is displayed in the UI, confirming that the native module works seamlessly within Flutter.
Benefits
Unified module declaration eliminates inconsistencies across platforms. UniModel enables transparent cross‑platform data transfer.
Compared with raw Flutter Channel :
No manual parameter parsing, reducing bugs.
Automatic Android/iOS alignment.
Massive Channel code is auto‑generated, easing maintenance.
Complex entities are serialized automatically.
Core Principles
Unify uses Dart as the interface definition language. The Dart Analyzer parses the source into a Dart AST, which is then transformed into a custom Unify AST that contains language‑agnostic mappings for Java, Objective‑C, and Dart code generation.
Multi‑language code generation templates are applied to the Unify AST, producing consistent implementations across all three platforms.
Comparison with Similar Solutions
Unify excels in batch exporting of dozens of SDKs with low engineering overhead, while Pigeon is more suitable for single‑module export or scenarios requiring additional language support such as C++.
Best Practices and Business Impact
Two architectural patterns emerged from Unify’s adoption:
UniFoundation : A reusable infrastructure that batch‑exports 16+ native SDKs, providing unified calls on Android, iOS, and Flutter. It has been adopted by both the food‑delivery and ride‑hailing driver apps.
UniBusiness : Business‑level modules built on top of UniFoundation, enabling three‑way unified calls and transparent entity transfer.
Since its introduction, Flutter has covered core flows in all three Didi International Food‑Delivery client sides, delivering over 50% efficiency gain and stable operation for more than two years.
Future Outlook
Unify will continue to evolve as a standard solution for Flutter hybrid development, adding features such as lightweight mixed‑routing based on PlatformView to further simplify large‑scale Flutter adoption.
Unify is now an open‑source project under the DiFlutter ecosystem. Users are encouraged to try it, experience it, and star the repository.
For more details, click "Read Original" to view the full open‑source project information.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
