Flutter 线下研发工具体验
如果无法正常显示,请先停止浏览器的去广告插件。
1. Flutter 线下研发工具体验
字节跳动 Flutter 开发者生态分享
孙恺
Swain
2. 目录
1. 我们的开发者遇到了什么困难
2. 字节跳动 Flutter 研发工具建设情况
3. 用 UME 为 Flutter 研发提速
1. UME 能够做什么
2. 为 UME 开发自定义插件
3. One more thing(UME Kits competition)
4. 未来的 Flutter 开发体验愿景
3. 我们的开发者遇到了什么困难
作为 Flutter 开发者,你是否有过如下抱怨?
4. 场景 1
Pub 组件管理
• 我们有很多私有 Pub 组件,如何发布、管理?
• 基础组件如何保障品质建设?
• 组件很多,如何让业务方找到所需的插件?
5. 场景 2
混合工程的开发环境、Flutter 多版本管理
• 多个 Flutter 工程分别使用不同的 Flutter 版本,引擎如何管理?
全局引擎切换麻烦
• iOS/Android/Web 不同技术栈的同学彼此不熟悉开发环境
开发环境配置麻烦,容易出错
• 在混合工程中调试 Flutter:要先跑起来 Native,然后 attach,不爽!
6. 场景 3
灵活的 Flutter 工程项目配置
• pubspec.yaml 配置是静态的,灵活性较低,无法在构建期间插入一些自定义的行为
• 如何使用本地配置覆盖远端配置的能力?(类似 Podfile_local)
• 有没有类似 Gradle 自动生成 BuildConfig,这种向运行时传递数据的能力?
• 如何隐式地生成代码,不需要手动调用代码生成器?
7. 场景 4
在应用内调试 Flutter App
• 官方提供的 DevTools 功能太少,要是能有个支持扩展的平台就好了
• 开发完成的功能,给到设计师验收,要是有个给设计师验收的工具就好了
• 在内测包(Release mode)中发现了问题,要是能有工具辅助调试就好了
8. 字节跳动 Flutter 研发工具建设情况
为研发流程提速,满足开发者诉求,提升开发者体验
9. Dart Pub 私有服务
Pub 组件管理
• unpub:开源的私有 Dart Pub 服务
https://github.com/bytedance/unpub
https://pub.dev/packages/unpub
• 基于 unpub,扩展功能
• 组件精选、业务共建组件推荐:让业
务快速找到所需组件
• Pana 组件评分:组件发布后执行
Pana 分析,给出组件评分
10. Dart Pub 私有服务
Pub 组件管理
• Pana 分析
11. Flutterw
混合工程的开发环境、Flutter 多版本管理
• Flutter 环境管理
• 自动安装缺失依赖项(android/iOS)
• 单个项目维度,提供彼此隔离的沙盒环境
12. Flutterw
混合工程的开发环境、Flutter 多版本管理
• 对⻬纯Flutter开发体验核心主要解决两个问题:
• IDE上点击Run按钮如何运行起宿主APP
• 如何自动Attach
• 按这个思路,整个编译流程如下:
• 拦截IDE的flutter run命令
• 自定义编译过程,运行起宿主APP
• 自动attach
13. Flutterw
混合工程的开发环境、Flutter 多版本管理
• flutter run命令提供了--use-application-binary参数,允许flutter可以直接运行一个可执行
文件,并自动attach;
• 因此基于宿主 app,调用flutter run --use-application-binary即可,也可以在壳工程上做
到类比纯Flutter的开发体验去开发调试宿主APP。这种方案最大的优点是不用较大的改动宿
主工程,接入成本较低。
14. Flutterw
混合工程的开发环境、Flutter 多版本管理
• 混编优化
• HostFlutterPlugin 模式: 只编译更新 Flutter 插件,不重复编译宿主 App
非首次编译运行 App 优化效果:Android 提升 3 倍,iOS 提升 7 倍
• HostOnlyDart 模式:只编译 Dart 代码,不重复编译所有 Native 代码
非首次编译运行 App 优化效果:Android 提升 8.7 倍,iOS 提升 2.4 倍
15. Ginkgo - Flutter build system
灵活的 Flutter 工程项目配置
• 100% 兼容 pubspec,支持工程所有配置项
• 支持 local 配置覆盖 remote 配置能力
• 支持定义 build Task,并支持 Task 编排
• 支持插件扩展
16. Ginkgo - Flutter build system
灵活的 Flutter 工程项目配置
17. UME - 应用内调试工具平台
Flutter 应用内调试工具
UME(flutter_ume) 是一款 Flutter 应用内调试工具平台,支持插件扩展。目前有字节跳动内部
版、社区开源版、ToB 商业化版本,全面支持 Null-Safety。
社区开源版,forks 100+,stars 1.5k+:
Pub:https://pub.dev/packages/flutter_ume
GitHub:https://github.com/bytedance/flutter_ume
18. 用 UME 为 Flutter 研发提速
Flutter 应用内调试工具
19. 用 UME 为 Flutter 研发提速
字节跳动内部版
Since 兼容 单测覆盖率
2020.07 Flutter
1.12 ~ 2.10 72%
接入业务 Debug 插件 Release 插件
20+
22 个
12 个
20. 用 UME 为 Flutter 研发提速
社区开源版
Since 兼容 单测覆盖率
2021.07 Flutter
2.0 ~ 2.10 66%
Forks / Stars Debug 插件 Release 插件
100+ / 1.5k
13 个
8 个
21. UME 能够做什么
社区开源版 - UI 插件包
22. UME 能够做什么
社区开源版 - UI 插件包
23. UME 能够做什么
社区开源版 - 性能工具包
24. UME 能够做什么
社区开源版 - 设备信息工具包
25. UME 能够做什么
社区开源版 - 其他工具
26. UME 能够做什么
社区优秀贡献 - Dio Inspector
Dio Inspector
Dio 网络请求查看插件
Alex Li
Flutter 社区开发者
Flutter GDE
CFUG member
27. UME 能够做什么
字节跳动内部版
• 分环境接入:基于 Conditional Import,通过编译命令传入,或 pubspec 读取标记;
同一份代码,UME 在 in-house 包中被引入,在线上版本中被自动移除
• 更多数据来源:基于 hook 技术,无侵入掌握来自 Flutter framework 层数据、多种网络库
的数据
• 更强大的插件:Flutter 宽版本兼容、http 请求的 mock 与 map local、内存泄漏检测等
28. 为 UME 开发自定义插件
如何开发自定义插件
1. 执行 flutter create -t package custom_plugin
创建一个插件包,可以是 package,也可以是 plugin
2. 修改插件包的 pubspec.yaml,添加依赖
dependencies:
flutter_ume: '>=0.3.0 <0.4.0’
3. 创建插件配置,实现 Pluggable 虚类
29. import 'package:flutter_ume/flutter_ume.dart';
class CustomPlugin implements Pluggable {
CustomPlugin({Key key});
@override
Widget buildWidget(BuildContext context) => const Container(
child: Center(child: Text('Custom Plugin')),
);
@override
String get name => 'CustomPlugin';
@override
String get displayName => 'CustomPlugin';
@override
void onTrigger() {}
@override
ImageProvider<Object> get iconImageProvider => NetworkImage('url');
}
30. 为 UME 开发自定义插件
如何开发自定义插件
4. 在工程中引入自定义插件
1. 修改 pubspec.yaml,添加依赖
dev_dependencies:
custom_plugin:
path: path/to/custom_plugin
2. 执行 flutter pub get
3. 引入包
import 'package:custom_plugin/custom_plugin.dart'
5. 在工程中注册插件
31. import 'package:flutter/foundation.dart';
import 'package:flutter_ume/flutter_ume.dart';
import 'package:custom_plugin/custom_plugin.dart';
void main() {
if (kDebugMode) {
PluginManager.instance
..register(CustomPlugin());
runApp(
UMEWidget(
child: MyApp(),
enable: true
)
);
} else {
runApp(MyApp());
}
}
32. 为 UME 开发自定义插件
快速接入第三方嵌入式插件
abstract class PluggableWithNestedWidget extends Pluggable {
Widget buildNestedWidget(Widget child);
}
33. 举例:flutter_ume 快速接入社区插件 cyclop
import "package:cyclop/cyclop.dart";
class ColorPicker extends StatefulWidget implements PluggableWithNestedWidget {
const ColorPicker({Key? key}) : super(key: key);
…
@override
String get name => 'ColorPicker';
...
@override
Widget buildNestedWidget(Widget child) {
return EyeDrop(child: child);
}
}
34. 为 UME 开发自定义插件
插件间通信
abstract class Communicable {
void handleParams(dynamic params);
}
abstract class PluggableLifeCycle {
void onActivate();
void onDeactivate();
}
35. 举例:插件间通信
class Palette extends StatefulWidget implements Pluggable, Communicable, PluggableLifeCycle {
Palette({Key? key}) : super(key: key);
Color? initialColor;
@override
void handleParams(dynamic params) {
if (params is Map && params.containsKey('initialColor')) {
initialColor = params['initialColor'];
}
}
@override
void onDeactivate() {
initialColor = null;
}
@override
void onActivate() {}
}
36. 为 UME 开发自定义插件
参考更多社区插件
社区开源版本的 flutter_ume 插件位于 https://github.com/bytedance/flutter_ume/tree/
master/kits 目录下,可以参考代码
37.
38. ? 欢迎共建
接受各种贡献方式
OOM 分析
数据库查看
状态管理调试器
网络环境管理
请求调试
优化现有插件 / 文档 网络代理
修改运行时结果
FPS 信息
路由调试
开发新插件
资源分析
文件管理
掉帧卡顿检测
慢速动画
优化 UME 框架
布局调试
为现有 Flutter Favorite 包
开发调试插件
UI 拖拽移动
网络 Mock
39. One more thing
UME Kits competition
插件开发竞赛活动
40. UME Kits competition
插件开发竞赛活动
本次活动针对社区版本 flutter_ume 插件开发
展开竞赛,优胜者将获得由字节跳动与
Google Flutter Team 赞助的丰厚奖品。
41. UME Kits competition
奖项设置
奖品 备注
一等奖 Pico Neo 3 VR 一体机 1 名
二等奖 苹果 HomePod mini 音箱 3 名
三等奖 大疆 DJI OM 4 SE 磁吸手机云台 6 名
优秀极客奖 200 元京东卡 10 名
参与贡献奖 Flutter 周边 前 50 位提交有效作品的开发者
42. UME Kits competition
比赛活动群
字节跳动 Flutter 技术交流群
43. UME Kits competition
参赛指南
1. 创建插件包 flutter create -t <package或plugin> name_of_kit
2. 在创建出来的包中,依赖 flutter_ume 进行开发
3. 开发完成后充分自测,在 test 目录中添加单元测试(可参考 https://github.com/
bytedance/flutter_ume/tree/master/kits/flutter_ume_kit_console/test 写法)
4. 在 README.md 中编写文档
5. 将插件演示效果截图或录屏保存到插件的 screenshots 目录下
44. UME Kits competition
参赛指南
6. 将 pubspec.yaml、README.md 文件与 lib、test、screenshots 目录(若为
plugin 则还包括对应平台的 native 代码目录,如 ios、android、web、windows、
macos、linux 等)一同压缩至 zip 压缩包,并以你的作品名称命名,如
name_of_kit.zip
7. 将压缩包以附件的形式,发送至 ume-kits-competition@bytedance.com,标题
为:"ume-kits-competition"。
45. UME Kits competition
参赛指南
ume-kits-competition@bytedance.com
46. UME Kits competition
注意事项
1. 提交作品需要符合“有效作品标准”,对不符合标准的参赛作品将无资格参与评奖
2. 若需要修改 flutter_ume 代码以支持插件能力,请 fork flutter_ume 仓库(https://
github.com/bytedance/flutter_ume),修改代码,并向 flutter_ume 仓库提交 Pull
Request。在提交作品的邮件正文中添加 Pull Request 的链接
3. 对于存在代码相似、创意相同、功能类似的参赛作品,以提交时间为评奖依据
4. 比赛组委会将在参赛作品评选结束后通过邮件联系选手,请务必保持邮箱畅通
47. UME Kits competition
注意事项
5. 参赛作品一旦发送到参赛邮箱,即认同该代码将以 MIT 协议开源,并同意贡献至
flutter_ume 开源仓库。参赛选手对参赛作品代码版权负责,对于代码可能存在的
版权、开源协议⻛险,承担责任
48. UME Kits competition
有效作品标准
1. 参赛作品压缩包中必须具备 pubspec.yaml、README.md 文件与 lib、test、
screenshots 目录,若为 plugin 则还包括对应平台的 native 代码目录
2. 参赛作品代码需要支持 Null-safety,最低支持 Flutter 2.0 版本,必须包含 test 单
元测试
3. 在提交作品前,需要在 flutter_ume 的 example 工程中将参赛作品接入测试,并成
功运行 example 工程,插件功能正常使用
49. UME Kits competition
有效作品标准
4. 参赛作品需要在活动提交时间内发送到参赛专用邮箱(ume-kits-
competition@bytedance.com),以参赛邮箱接收到邮件的时间为准,不在活动提
交时间内提交的作品无效
50. UME Kits competition
比赛时间
4 月 9 日 5 月 30 日 6 月 15 日 6 月 20 日
比赛启动 作品提交截止 评选截止 结果公示
51. UME Kits competition
参赛细则请⻅
https://bytedance.feishu.cn/docx/doxcnwlGZMwGRC7zNs5UZlURPXc
活动最终解释权归字节跳动所有
52. UME Kits competition
比赛活动群
字节跳动 Flutter 技术交流群
53. 未来的 Flutter 开发体验愿景
54. 未来的 Flutter 开发体验愿景
开发者体验建设工作
• 组件 / 工具品质建设
• 适配 Flutter 生态多平台
• 提升组件单元测试覆盖率,提高组件品质
• 强化现有能力,优化开发者体验
• 更健全的组件管理服务
• 组件在线演示
• 更细粒度的组件权限管理能力
• ……
55. 未来的 Flutter 开发体验愿景
开发者体验建设工作
• 拥抱社区生态
• 现有工具/组件拥抱社区生态,扩大社区贡献
• 内部、外部版本同构,降低开源成本
我们期待与各位优秀的 Flutter 社区的开发者一同创造 Flutter 更好的未来!
56. 谢谢