Skip to content

Commit 1a59112

Browse files
committed
update readme
1 parent 1fabc91 commit 1a59112

File tree

8 files changed

+584
-138
lines changed

8 files changed

+584
-138
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@
66

77
# Conventional directory for build outputs
88
build/
9+
*.bkp
10+
*.dtmp

README.md

Lines changed: 208 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,222 @@
1+
[English Version](): is working in progress...
2+
3+
# Unify:Flutter-原生混合通信
4+
15
## 介绍
2-
Unify 旨在为Flutter和其宿主平台之间的交互提供类型安全的代码生成解决方案。
36

4-
## 特性
5-
* **多端接口统一**:借助代码自动生成技术和通用接口模板,实现多端接口的标准化和统一化。
6-
* **语言易扩展**:内置了独特的AST协议和通用的代码模板,利用编程式思想进行多语言扩展。
7-
* **代码模块化**:按照模板目录结构生成和存储代码,模型与接口完全分离解耦。
8-
* **简单易上手**:一条命令实现跨端语言调用,开发者无需手动编写繁琐的通信代码,只需专注于接口的定义。
7+
Unify 是一个 Flutter 代码生成器,解决 Flutter 混合开发场景下,原生模块与 Flutter 模块间的大规模通信问题。
8+
9+
Unify 允许开发者声明平台无关的模块抽象,灵活注入实现,并生成 Flutter、Android、iOS 多平台下统一调用 SDK。
10+
11+
基于 Unify 的代码生成技术,允许开发者使用 Dart 语言声明模块接口与实体。对于实现注入方式,开发者可选择注入原生实现(Android、iOS)或 Flutter 实现。
12+
13+
整体原理如下:
14+
15+
![](docs/public/unify-arch.png)
16+
17+
Unify 擅长解决:
18+
19+
- 大量原生模块高效导入 Flutter
20+
- 大量 Flutter 模块高效导入原生
21+
- 解决大量 Channel 难以维护的问题
22+
- 原生与 Flutter 并存下的**混合架构分层**
23+
24+
Unify 由滴滴出行国际化外卖团队自研,广泛应用于滴滴国际化外卖及国际化出行业务。有效支撑业务 Flutter 大规模落地。
25+
26+
## Installation
27+
28+
Unify 是一个使用 Dart 开发的命令。
29+
30+
在 Flutter 工程的 `pubspec.yaml` 中添加 `dev_dependencies`
31+
32+
```yaml
33+
dev_dependencies:
34+
unify: latest_version
35+
```
36+
37+
> 注:目前 Unify 尚未发布 pub.dev,可先通过 git 依赖方式体验。后续会正式发布 pub.dev,敬请期待。
38+
39+
git 依赖:
40+
41+
```yaml
42+
dev_dependencies:
43+
unify:
44+
git: git@github.com:maxiee/Unify.git
45+
```
46+
47+
执行 `flutter pub get` 拉取依赖。之后即可运行 Unify:
48+
49+
```sh
50+
flutter pub run unify api
51+
```
52+
53+
> 注:执行 Unify 命令通常需伴随一系列参数,具体可使用方式可参见 Getting Started。
54+
55+
56+
## Getting Started
57+
58+
以最基础的使用场景为例:有一个原生 SDK,同时包含 Android、iOS 版本,开发者需要对其进行统一封装,并导入到 Flutter 中。
59+
60+
> 本例实例代码位于 `examples/01_uninativemodule_demo` 下。
61+
62+
运行 Demo:
63+
64+
首先 clone 工程,并进入 `01_uninativemodule_demo` 目录:
65+
66+
```sh
67+
git clone git@github.com:didi/Unify.git
68+
cd ./Unify/01_uninativemodule_demo
69+
```
70+
71+
`01_uninativemodule_demo` 是一个普通的 Flutter App,其功能是:原生侧(Android/iOS)各实现一个系统信息模块,统一导入 Flutter,在 Flutter 中统一调用。
72+
73+
不同之处在于,**项目下有一个 interface 目录,这是我们声明 Unify 模块的地方**。其中包含两个类:
74+
75+
首先是一个模块声明,`@UniNativeModule` 表示该模块的实现由 Native 原生提供(NativeModule):
76+
77+
```dart
78+
// device_info_service.dart
79+
@UniNativeModule()
80+
abstract class DeviceInfoService {
81+
/// 获取设备信息
82+
Future<DeviceInfoModel> getDeviceInfo();
83+
}
84+
```
85+
86+
同时可以看到,`getDeviceInfo` 返回一个 `DeviceInfoModel`,声明如下:
87+
88+
```dart
89+
// device_info_model.dart
90+
@UniModel()
91+
class DeviceInfoModel {
92+
/// 系统版本
93+
String? osVersion;
94+
95+
/// 内存信息
96+
String? memory;
97+
98+
/// 手机型号
99+
String? plaform;
100+
}
101+
```
102+
103+
这是什么意思呢?**使用 Unify 之后,开发者只需关注跨端统一模块的声明**,如果由原生侧提供实现使用 `@UniNativeModule` 注解,如果由 Flutter 侧提供实现使用 `@UniFlutterModule` 注解,如果使用复杂实体使用 `@UniModel` 注解。
104+
105+
接口声明好后,执行项目目录下的 `gen_uni_code.sh` 脚本:
106+
107+
```sh
108+
flutter pub run unify api\
109+
--input=`pwd`/interface \
110+
--dart_out=`pwd`/lib \
111+
--java_out=`pwd`/android/src/main/java/com/example/uninativemodule_demo \
112+
--java_package=com.example.uninativemodule_demo \
113+
--oc_out=`pwd`/ios/Classes \
114+
--dart_null_safety=true \
115+
--uniapi_prefix=UD
116+
```
117+
118+
这会调用 Unify 生成器。其中:
119+
120+
- `input`:指定接口输入目录
121+
- `dart_out`:指定 Dart 部分输出目录
122+
- `java_out`:指定 Java 部分输出目录
123+
- `java_package`:指定对应的 Java 报名
124+
- `oc_out`:iOS 的 Objective-C 输出目录
125+
- `dart_null_safety`:是否启用空安全
126+
- `uniapi_prefix`:(可选),生成器会生成一个 Unify 类,这里提供一个前缀,避免多个使用 Unify 的库间相互冲突。
127+
128+
执行后,在工程内会生成以下文件:
129+
130+
由于实现由原生侧注入,所以我们使用 `@UniNativeModule`,在原生侧生成供注入的接口:
131+
132+
- Android:[DeviceInfoService.java](https://github.com/didi/Unify/blob/master/examples/01_uninativemodule_demo/android/src/main/java/com/example/uninativemodule_demo/DeviceInfoService.java)
133+
- iOS:[DeviceInfoService.h](https://github.com/didi/Unify/blob/master/examples/01_uninativemodule_demo/ios/Classes/DeviceInfoService.h)[DeviceInfoService.m](https://github.com/didi/Unify/blob/master/examples/01_uninativemodule_demo/ios/Classes/DeviceInfoService.m)
134+
135+
有了这些接口,由开发者继承补充模块的原生代码实现:
136+
137+
- Android 实现类:[DeviceInfoServiceImpl.java](https://github.com/didi/Unify/blob/master/examples/01_uninativemodule_demo/example/android/app/src/main/java/com/example/uninativemodule_demo_example/DeviceInfoServiceImpl.java)
138+
- Android 注册实现:[MainActivity.java](https://github.com/didi/Unify/blob/master/examples/01_uninativemodule_demo/example/android/app/src/main/java/com/example/uninativemodule_demo_example/MainActivity.java)
139+
140+
- iOS 实现类:[DeviceInfoServiceVendor.h](https://github.com/didi/Unify/blob/master/examples/01_uninativemodule_demo/example/ios/Runner/DeviceInfoServiceVendor.h)[DeviceInfoServiceVendor.m](https://github.com/didi/Unify/blob/master/examples/01_uninativemodule_demo/example/ios/Runner/DeviceInfoServiceVendor.m)
141+
- iOS 注册实现:[AppDelegate.m](https://github.com/didi/Unify/blob/master/examples/01_uninativemodule_demo/example/ios/Runner/AppDelegate.m)
142+
143+
我们可以看到,同时生成了跨端 `UniModel` 实体,**在各平台下都能直接使用 Model 类,由 Unify 抹平底层序列化传递**
144+
145+
- Android:[DeviceInfoModel.java](https://github.com/didi/Unify/blob/master/examples/01_uninativemodule_demo/android/src/main/java/com/example/uninativemodule_demo/DeviceInfoModel.java)
146+
- iOS:[DeviceInfoModel.h](https://github.com/didi/Unify/blob/master/examples/01_uninativemodule_demo/ios/Classes/DeviceInfoModel.h)[DeviceInfoModel.m](https://github.com/didi/Unify/blob/master/examples/01_uninativemodule_demo/ios/Classes/DeviceInfoModel.m)
147+
- Flutter:[device_info_model.dart](https://github.com/didi/Unify/blob/master/examples/01_uninativemodule_demo/lib/device_info_model.dart)
148+
149+
至此,便完成了**将一个原生模块统一导入 Flutter**
150+
151+
在 Flutter 中,可以以统一方式调用:
152+
153+
```dart
154+
OutlinedButton(
155+
child: const Text("获取设备信息"),
156+
onPressed: () {
157+
DeviceInfoService.getDeviceInfo().then((deviceInfoModel) {
158+
setState(() {
159+
_platformVersion = "\n${deviceInfoModel.encode()}";
160+
});
161+
});
162+
},
163+
),
164+
```
165+
166+
![](./docs/public/unify-demo.png)
167+
168+
Bingo!是不是像调用一个 Flutter 模块一样清晰、简单!
169+
170+
乘热划一下重点,Unify 带来了哪些好处?
171+
172+
1. `统一模块声明`:在任何平台下,统一的模块,统一的接口,完全对其,避免实现不一致
173+
2. `UniModel`:模块支持声明实体,跨平台生成实体类,无感透明跨端传输
174+
3. 相较于 Flutter Channel,避免了:
175+
1. 手动解析参数已出错
176+
2. Android、iOS 双端难以对齐
177+
3. 大量 Channel 下不易维护
178+
4. 复杂实体序列化管理成本高
179+
180+
## Decision Tree
181+
182+
我们总结了如下决策流程:
183+
184+
![](./docs/public/unify-decision-tree.png)
185+
186+
187+
## More Examples
188+
189+
在 Getting Started 中,给出了最基础、使用场景最多的【原生实现导入 Flutter】。Unify 的能力远不止这些。从简单的单一 SDK 封装,到复杂的企业级 App 大规模模块导出,Unify 都能够支持。
190+
191+
我们通过实例应用的方式,对这些典型场景及业务模式进行介绍:
192+
193+
|案例|说明|适用场景|
194+
|---|---|---|
195+
|[01_uninativemodule_demo](https://github.com/didi/Unify/tree/master/examples/01_uninativemodule_demo)|UniNativeModule 演示|如何将一个原生模块(Android/iOS双端实现)高效导入Flutter、实现统一调用|
196+
|[02_unifluttermodule_demo](https://github.com/didi/Unify/tree/master/examples/02_unifluttermodule_demo)|UniFlutterModule 演示|如何将一个 Flutter 模块,高效导入原生(Android/iOS),实现统一调用|
197+
198+
## Documentation
199+
200+
对于更多高级用法,请参见详细文档。
9201

10-
## 开始使用
11202
* 查看文档请参考 [Unify文档](docs/README.md)
12203
* 想快速体验如何使用,请参考 [快速开始](docs/02.快速开始/README.md)
13204
* 想了解 Unify 提供哪些能力,请参考 [基础能力](docs/06.基础能力/README.md)
14205
* 想了解 Unify 模块设计原理,请参考 [原理概述](docs/08.原理概述/README.md)
15206
* 想了解更多 Unify CLI 的使用说明,请参考 [CLI 使用教程](docs/04.CLI 使用教程.md)。
16207

17-
## 简单演示
18-
简单感受一下使用 Unify 开发`UniModel``UniFlutterModule``UniNativeModule`类型模板。
19-
20-
| 模板类型 | Unify 模板代码 |
21-
| ---- | ---- |
22-
| UniModel |![UniModel](https://img-hxy021.didistatic.com/static/starimg/img/pUTEtJURjh1696837559178.png)|
23-
| UniFlutterModule |![UniFlutterModule](https://img-hxy021.didistatic.com/static/starimg/img/SSr324LZQ31696836327061.png)|
24-
| UniNativeModule |![UniNativeModule](https://img-hxy021.didistatic.com/static/starimg/img/8EPR2HVl6J1696836327036.png)|
25-
26-
## 关联用例
27-
| Demo | 说明 |
28-
| :-------- | :------ |
29-
| example | 项目中的 example 工程是 Unify 创建的完整示例工程,主要实现 **《Native 同步定位信息到 Flutter》****《Flutter 向 Native 获取设备信息》**功能。 |
208+
> 注:目前我们也在积极整理文档,如果在使用、理解上有任何问题,欢迎提交 Issue 反馈、交流!
30209
31210
## 协议
211+
32212
<img alt="Apache-2.0 license" src="https://www.apache.org/img/ASF20thAnniversary.jpg" width="128">
33213

34214
Unify 基于 Apache-2.0 协议进行分发和使用,更多信息参见 [协议文件](LICENSE)
35215

36216
## 成员
217+
218+
研发团队:
219+
37220
[maxiee](https://github.com/maxiee),
38221
[zhugeafanti](https://github.com/zhugeafanti),
39222
[piglet696](https://github.com/piglet696),
@@ -48,4 +231,9 @@ Unify 基于 Apache-2.0 协议进行分发和使用,更多信息参见 [协议
48231
[jiawei1203](https://github.com/jiawei1203),
49232
[Whanter](https://github.com/Whanter)
50233

234+
## Contribution
235+
236+
如果在使用、理解上有任何问题,欢迎提交 Issue 反馈、交流!
237+
238+
欢迎您的交流、贡献!
51239

docs/public/unify-arch.png

68 KB
Loading

docs/public/unify-decision-tree.png

45.2 KB
Loading

docs/public/unify-demo.png

31.6 KB
Loading

0 commit comments

Comments
 (0)