Flutter 动态化 SDK 接入指引
一、隐私安全说明
Flutter 动态化 SDK
版本:0.0.6
更新时间:2025年12月1日
SDK介绍:为Flutter开发框架提供动态化能力,方便开发者在线更新或修复问题
服务提供方:深圳市腾讯计算机系统有限公司
接入指引:Flutter 动态化 SDK 接入指引
隐私保护规则:《Conch 动态化 SDK 隐私保护规则》
二、获取 SDK 和 License
Flutter动态化属于限制开放功能,有兴趣的用户请联系我们,以获取SDK和相关使用权限。

三、SDK接入
Conch-Flutter SDK 通过改造 Dart 编译器,并配套自主研发的 Dart 解释器,构建了一套完整的运行时服务体系,实现了对 Flutter 应用的动态修复与热更新能力。
Conch-Flutter SDK 接入流程主要包括以下几个环节:
- 首先,需要完成 Conch-Flutter SDK 环境搭建,确保开发环境配置完整,为后续开发和调试奠定基础。
- 接着,在应用启动阶段初始化 ConchLoaderAPI,这一步骤至关重要,它负责动态加载和应用补丁,从而实现业务代码的热修复能力。
- 随后,Conch-Flutter SDK编译基准包的同时会自动生成一个
conch_base_<versionCode>.json格式的符号文件,该文件详细记录了当前安装包中所有方法及其符号信息,为后续补丁的精准定位和替换提供关键依据。 - 在基准包的基础上,开发者对业务代码进行修复,并完成热修相关的代码改造,确保补丁能够正确加载并生效。
- 最后,制作补丁包,并通过 Shiply 平台进行发布和管理,实现 Flutter 应用的动态更新和维护。
3.1 配置 Conch-Flutter SDK
1. 克隆Conch-Flutter仓库
克隆仓库命令:
git clone https://cnb.cool/tencent-tds/Conch-Flutter
认证信息:
- 第一次拉取时会要求输入认证信息,如图所示:

输入用户名和token:
- Username:
cnb - Password:输入我们提供的Token作为密码
切换到指定版本:
git checkout flutter3.22.3_extRelease1.6.13
版本Tag命名规则说明:
Tag的命名格式为:flutter{Flutter版本号}_extRelease{ConchSDK版本号}
- 示例:
flutter3.22.3_extRelease1.6.13 - Flutter版本号:3.22.3(对应Flutter框架版本)
- ConchSDK版本号:1.6.13(对应Conch动态化SDK版本)
注意事项:
- 请确保使用与您项目Flutter版本匹配的Tag版本
- 不同版本的Conch-Flutter可能对应不同的Flutter版本,请根据实际需求选择合适的Tag
- 如果遇到认证问题,请确认Token是否有效或联系技术支持
- 重要:如果项目路径包含中文或特殊字符,请将项目移动到纯英文路径下,否则可能导致编译失败
- 首次使用前,建议执行
flutter clean清理缓存,然后执行flutter pub get重新获取依赖
2. 配置环境变量
将 Conch 定制的 FlutterSDK 路径加入环境变量(以 macOS 为例):
export PATH=/{YourPath}/conch-flutter/bin:$PATH
- 替换
{YourPath}为实际路径。
3. macOS 弹窗问题处理
macOS 上运行某些未经公证的应用或工具时,系统会弹出安全警告窗口(如“无法打开应用”或“来自身份不明的开发者”提示)。
Conch SDK 及其相关工具链经过合规检测,但由于某些二进制文件以及工具链的特殊性,运行时会触发系统的安全防护,导致弹窗提示。这是一种正常现象,不影响 Conch 的功能和开发使用。
macOS 会给从网络下载的应用或文件打上 com.apple.quarantine 属性(即 Quarantine),导致运行时弹窗。可以通过解除该属性来避免弹窗。我们在后续新发布的SDK包中都添加了相关的解除脚本,脚本执行过程中需要输入 sudo 密码,使用步骤如下:
cd /{YourPath}/conch-flutter
sh ./xattr_quarantine_inFlutter.sh
将会得到以下输出:
正在检测并解除 Flutter 工具 quarantine 属性...
flutter目录 {YourPath}/conch-flutter
已经解除flutter工具的quarantine属性,避免弹窗!
如有其他问题,可联系我们。
4. 验证配置
执行以下命令,检查 FlutterSDK 是否配置成功:
flutter --version
输出类似如下内容即为成功:
enheng@LUCKIERGONG-MC2 ~ % flutter --version
ConchFlutter execute: --version
Flutter 3.22.3 • Conch extRelease1.6.13 • channel [user-branch] • https://cnb.cool/tencent-tds/Conch-Flutter
Framework • revision aa73bc9e53 (11 days ago) • 2025-11-20 17:23:32 +0800
Engine • revision 27fce7e964
Tools • Dart 3.4.4 • DevTools 2.34.1
flutter doctor -v
输出类似如下内容即为成功:
ConchFlutter execute: doctor -v
[!] Flutter (Channel [user-branch], 3.22.3, on macOS 15.6 24G84 darwin-arm64 (Rosetta), locale zh-Hans-CN)
! Flutter version 3.22.3 on channel [user-branch] at /Users/enheng/development/conch-flutter-cnb
Currently on an unknown channel. Run `flutter channel` to switch to an official channel.
If that doesn't fix the issue, reinstall Flutter by following instructions at
https://flutter.dev/docs/get-started/install.
! Upstream repository https://cnb.cool/tencent-tds/Conch-Flutter is not a standard remote.
Set environment variable "FLUTTER_GIT_URL" to https://cnb.cool/tencent-tds/Conch-Flutter to dismiss this
error.
• Framework revision aa73bc9e53 (11 days ago), 2025-11-20 17:23:32 +0800
• Engine revision 27fce7e964
• Dart version 3.4.4
• DevTools version 2.34.1
• If those were intentional, you can disregard the above warnings; however it is recommended to use "git"
directly to perform update checks and upgrades.
[✓] Android toolchain - develop for Android devices (Android SDK version 36.1.0)
• Android SDK at /Users/enheng/Library/Android/sdk
• Platform android-36, build-tools 36.1.0
• Java binary at: /Users/enheng/Library/Java/JavaVirtualMachines/ms-17.0.16/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment Microsoft-11926164 (build 17.0.16+8-LTS)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 16.4)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 16F6
• CocoaPods version 1.16.2
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2025.1)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 21.0.6+-13391695-b895.109)
3.2 配置Conch依赖
1. pubspec.yaml 中添加 Conch 相关依赖
dependencies:
conch_api:
sdk: flutter
2. 添加 Conch 插件配置
# 在 yaml 文件顶层,而不是在 dependencies 中添加
conch:
enable: true # 是否开启Conch
noPatchSingleton: true # 是否开启单例自动排除和检测
versionCode: 1.0.0 # 本次构建的版本
targetBaseVersions: 1.0.0 # 在制作补丁时生效,基于 targetBaseVersions 版本构建补丁
conchMode: all&hotfix # Conch 生效模式,hotfix(函数级别热更)、all&hotfix(自由控制函数或类的热更)
licensePath: ./conch_license # 授权证书文件路径
配置参数详细说明:
注意 :
enable:参数为 false 时,不会启动 Conch 热更功能。建议在日常开发和调试阶段设置为 false,以缩短编译和调试时间;需要发版并生成补丁包时再设置为 true。noPatchSingleton:是否开启单例自动排除和检测。开启后Conch会自动检测并排除单例类,避免热更新时产生单例冲突问题。建议在开发阶段开启此配置,自动处理单例问题;对于重要的单例类,建议同时手动使用@PatchExclude()注解进行手动排除,确保稳定性。versionCode:本次构建的产物版本号,同时将会在.dart_tool/conch_build目录下生成当前产物的标记文件,符号文件以conch_base_<versionCode>.json命名 。targetBaseVersions: 在制作补丁时将会依据该版本号在conch_base目录下匹配对应符号文件作为基准,生成相应的补丁。conchMode:hotfix 为函数级别热更,all&hotfix 可自由控制函数或页面的热更。具体特点和使用方法将在后续进行详细介绍。licensePath:必填需确保证书文件已放置在对应位置,在验证证书后 Conch 热修才能生效。
热修单例原理介绍
单例模式确保一个类只有一个实例,但Conch-Flutter热修复会在补丁包中创建新实例,导致同时存在两个单例对象,引发数据不同步和系统异常。
解决方案:
- 自动检测:设置
noPatchSingleton: true,Conch自动识别并排除单例类打入补丁 - 手动控制:依据编译提示,使用
@PatchExclude()注解精准排除关键单例类。@PatchExclude()注解默认排除整个文件,当需要排除单个接点时用@PatchExclude(onlyNode: true)。
3.3 初始化ConchLoaderAPI
在正式使用 Conch 进行函数或页面的热修复之前,必须先完成 ConchLoaderAPI 的初始化,并调用补丁加载方法。具体流程为:先调用 ConchLoaderAPI.init 方法完成加载器初始化,再调用ConchLoaderAPI.getPatchLoadResult方法拉取并加载补丁。这一步是实现热修能力的前提,只有初始化完成后,Conch 才能正确识别当前应用环境并加载适配的补丁包。
通过初始化ConchLoaderAPI,应用能够与补丁分发平台 Shiply 建立连接,传递必要的身份和环境信息,从而实现补丁的精准下发和动态加载。如果未进行初始化或者初始化参数有误,后续的热修相关逻辑将无法生效。
3.3.1 ConchLoaderAPI.init() 使用说明
| 参数名 | 含义 | 说明 |
|---|---|---|
appId | 应用 Shiply ID | 在 Shiply 发布平台获取,需与平台配置一致,用于唯一标识应用。 |
appKey | 应用Shiply appkey | 在 Shiply 发布平台获取,需与平台配置一致,用于安全校验。 |
moduleName | 模块名称 | 在 Shiply 发布平台创建的模块名,需与平台配置一致。 |
env | 环境名称 | 默认为 online(正式环境),其他环境请参考 Shiply 平台界面中的环境ID。 |
deviceId | 设备ID | 用于 Shiply 平台灰度发布、白名单等场景,便于精准控制补丁下发对象。 |
appVersion | 应用版本号 | 应用的版本号,不仅用于标识 App 本身的发布版本,也作为 Shiply 平台下发补丁时版本控制依据。 |
remoteFirst | 远端优先 | 远端产物优先:每次启动都优先检查远端是否有更新,检查期间显示加载状态。(详细解释见下文注意事项) |
debugEnable | 调试开关 | 是否开启调试模式:开启后日志输出等级为Debug,加载的Widget上会显示调试信息 |
ConchLoaderAPI.init()注意事项:
appId、appKey、moduleName、env必须与 Shiply 发布平台配置完全一致,否则无法正确获取补丁。deviceId可用于灰度发布、白名单等精准控制场景。appVersionapp的版本号,也用于shiply平台补丁下发的版本控制。remoteFirst远端产物优先,为true时每次启动都优先检查远端是否有更新,如果有更新就会拉取。没有会直接使用本地的补丁包。为false时不会检查远端是否有更新,本地有补丁包时会直接加载本地补丁。debugEnable在开发调试阶段开启,正式发布前务必关闭。
PS:关于 appVersion、targetBaseVersions、versionCode 的设置说明
在集成 Conch 时,涉及三个版本号参数,分别是 pubspec.yaml 文件中Conch插件配置的 versionCode、targetBaseVersions 以及 ConchLoaderAPI.init() 中的 appVersion 。它们的作用和关系如下:
1. 各版本号说明
appVersion :该版本号用于标识产品发布的具体版本,同时也用于 Shiply 平台的补丁下发版本控制。平台将根据该版本号字符串进行完全匹配,以确定是否推送对应补丁。
targetBaseVersions :制作补丁时的基准包版本,生成补丁时会在 conch_base 文件夹中加载该版本的符号文件作为补丁制作的基准。
versionCode :在releas模式下编译都会在
.dart_tool/conch_build目录下生成当前产物对应的符号文件(如conch_base_${versionCode}.json)。
2. 编译基准包时
appVersion、targetBaseVersions、versionCode三者完全一致即可。- 生成APP产物同时,会在
.dart_tool/conch_build下生成对应的基准符号文件。 - 基准包的符号文件需要归档保存,以便后续为该基准包制作补丁时使用。
3. 制作补丁包时
targetBaseVersions需要与appVersion完全一致。详细的补丁制作流程见下文补丁制作。versionCode的设置:- 递增
versionCode,如 1.0.0+1,1.0.0+2 等,便于区分和管理。- 如果不需要归档,
versionCode可与targetBaseVersions保持一致。 - 例如:已生成 1.0.0 版本的基准包并归档了符号文件,现需为该版本制作补丁,则配置如下:
- appVersion: 1.0.0
- targetBaseVersions: 1.0.0
- versionCode: 1.0.0(不需要归档符号文件时)或 1.0.0+1(便于区分和管理)。建议结合git分支来管理。
- 如果不需要归档,
4. Shiply 平台补丁下发条件设置
- 下发条件必须严格等于基准包版本号(如 ==1.0.0),
- 切勿使用大于等于(>=1.0.0)等宽泛条件,以避免补丁被错误下发到其他版本。
3.3.2 ConchLoaderAPI.getPatchLoadResult() 加载补丁
在 ConchLoaderAPI.init 初始化成功后,可以调用 ConchLoaderAPI.getPatchLoadResult 方法获取补丁加载结果。
// 获取当前补丁的加载结果
// 未加载时是否触发预加载,默认为 false
ConchLoaderAPI.getPatchLoadResult({preload: true});
参数说明
| 参数 | 类型 | 详细信息 | 说明 |
|---|---|---|---|
preload | Boolean | 获取当前补丁的加载结果 | 默认为 false。当 preload 为 true 时,若补丁平台有可用补丁,方法会自动下载并加载补丁;为 false 时,则不会预先下载补丁,而是在需要加载时才进行加载,此时会显示加载界面。 |
注意事项
- 该方法需在
ConchLoaderAPI.init初始化成功后调用,获取当前补丁的加载结果。
3.3.3 初始化ConchLoaderAPI并加载补丁示例代码
import 'package:conch_api/conch_api.dart';
void main() async {
// 自定义日志输出
ConchLoaderAPI.setCustomLogger((level, tag, message) {
print('[Custom ${level.toString().split('.').last[0]}] $tag: $message');
});
// 1. 初始化补丁平台参数(请根据实际情况替换为你的参数)
final appId = "a1b2c3d4e5f";// Shiply平台分配的AppId
final appKey = "123e4567-e89b-12d3-a456-426614174000"; // Shiply平台分配的AppKey
// 构建ConchParams对象,包含所有初始化所需参数
final params = ConchParams(
appId: appId,
appKey: appKey,
moduleName: "conch_module", // 替换为实际的模块名
deviceId: "12345", // 设备ID,用于灰度/白名单等场景
appVersion: "1.0.0", // 当前应用版本,对应补丁下发的目标版本
remoteFirst: true, // 启动时优先拉取远端补丁
debugEnable: true, // 开发阶段建议开启,正式发布前请关闭
);
// 2. 定义补丁加载结果回调
PatchLoadCallback patchLoadCallback = (patchLoadResult) => () {
if (patchLoadResult == null) {
print('没有可下载的补丁包');
} else {
// 补丁信息获取成功
final moduleName = patchLoadResult.moduleName;
final md5 = patchLoadResult.md5.isEmpty
? ''
: patchLoadResult.md5.substring(0, 8); // 取前8位MD5做展示
final version = patchLoadResult.version;
print('[$moduleName] 补丁包md5为 $md5,版本号为 $version');
}
};
// 3. 初始化ConchLoaderAPI
// 建议在应用启动的最早阶段(如main函数)进行初始化,确保补丁能尽早生效
ConchLoaderAPI.init(params, patchLoadCallback: patchLoadCallback);
// 4. 异步方法加载补丁
// preload: true 表示预加载补丁
// 建议在初始化后立即调用,保证补丁及时拉取
ConchLoaderAPI.getPatchLoadResult(preload: true);
// 5. 启动Flutter应用
runApp(MyApp());
}
3.3.4 初始化参数与shiply平台对应关系


四、 改造项目以支持页面级动态化
在完成 ConchLoaderAPI 的初始化后,开发者即可对需要热修复的页面进行改造。Conch 支持两种热修模式:函数热更新(hotfix 模式)和页面与函数热更新(all&hotfix 模式)。
- 如果您的项目只需要进行函数级别的热更(hotfix 模式)不涉及页面的热修,无需进行额外改造,可直接进行编译基准包操作;
- 如果您需要进行页面级别的热更,需要完成接下来页面与函数热更(all&hotfix模式)中的改造过程,然后再进行编译基准包操作。
4.1 页面与函数热更改造(all&hotfix模式)
在 hotfix 模式的基础上,all&hotfix 模式不仅保留了函数级热修的能力,还进一步扩展了页面级热修的能力。开发者可以根据实际业务需求,灵活选择热更的粒度。这里将详细介绍页面热修的改造方式。
页面热更的接入过程主要包括以下两步:
- 增加页面映射表并加上
@ConfigGenerate()注解
新增并维护一个页面映射表如下page_map_table所示 ,建议将其放置在与页面路由代码相同的文件中,并使用@ConfigGenerate()注解进行标记。Conch 会自动解析并记录页面的入口相关信息,包括页面对应的 Dart 文件路径、页面类名称、页面构造方法等。
```dart
// 页面配置信息
@ConfigGenerate()
final Map<String, Function> page_map_table = {
//需要进行热修的页面
"image": ImagePage.new,
"list": ListPage.new,
};
```
注意:
page_map_table中的 key(如 "image")就是后续ConchLoaderAPI.load的pageName参数。
将页面的创建过程通过
ConchLoaderAPI.load接口进行替换。
推荐在页面路由跳转或页面构建的入口处,使用ConchLoaderAPI.load进行页面的动态创建。ConchLoaderAPI.load参数说明:参数名 类型 说明 必选 备注 pageNameString热修页面的名字,需与 @ConfigGenerate()生成的映射表中的key严格对应。是 唯一标识热修页面 defaultWidgetBuilderWidget Function(dynamic)补丁包缺失或者热修页面在补丁包中不存在时构建默认页面的回调,保证页面正常显示。 是 返回默认的原生页面 Widget positionalParametersList<dynamic>?传递给页面构造函数的位置参数列表(可选)。 否 适用于位置参数构造函数 namedParametersMap<String, dynamic>?传递给页面构造函数的命名参数(可选)。 否 适用于命名参数构造函数 页面热修改造示例:
import 'package:conch_api/conch_api.dart';
/// 使用 @ConfigGenerate() 注解标记页面映射表
/// 该注解会自动生成热修补丁入口信息,
/// 使得热修框架能根据页面名称动态创建对应页面实例。
()
final Map<String, Function> page_map_table = {
// 页面名称 "image" 对应 ImagePage 的构造函数
"image": ImagePage.new,
// 页面名称 "list" 对应 ListPage 的构造函数
"list": ListPage.new,
};
/// 一、路由生成函数,负责根据路由名称返回对应页面的路由
/// 这里通过 ConchLoaderAPI.load 实现页面的动态加载(热修接入点)
/// 通过 pageName 定位热修包中的页面资源,
/// 并通过 defaultWidgetBuilder 提供原生页面的回退方案。
Route<dynamic>? OnGenerateRoute(RouteSettings settings) {
switch (settings.name) {
case 'image':
// 原生页面创建方式
// return MaterialPageRoute(builder: (_) => ImagePage(title: "native加载的页面"));
// 改造为热修页面动态加载:
// - pageName: "image",对应热修包中的页面标识
// - defaultWidgetBuilder: 当热修页面不可用时,构建原生 ImagePage
// - namedParameters: 传递给热修页面的命名参数,覆盖默认参数
return MaterialPageRoute(
builder: (_) => ConchLoaderAPI.load(
"image",
(_) => ImagePage(title: "native加载的页面"),
namedParameters: {"title": "热修加载的页面"},
),
);
case 'list':
// 原生页面创建方式
// return MaterialPageRoute(builder: (_) => ListPage("参数1", "参数2", "参数3"));
// 改造为热修页面动态加载:
// - pageName: "list"
// - defaultWidgetBuilder: 构建原生 ListPage,传入默认参数
// - positionalParameters: 传递给热修页面的位置参数列表
return MaterialPageRoute(
builder: (_) => ConchLoaderAPI.load(
"list",
(_) => ListPage("native参数1", "native参数2", "native参数3"),
positionalParameters: ["热修参数1", "热修参数2", "热修参数3"],
),
);
// 其他页面直接返回原生页面
case 'anim':
return MaterialPageRoute(builder: (_) => AnimationPage());
// 未匹配到路由,返回404页面
default:
return MaterialPageRoute(
builder: (_) => Scaffold(
body: Center(child: Text('Page not found')),
),
);
}
}
/// 二、路由表,结合 ConchLoaderAPI.load 实现热修页面动态加载
/// 这里的 key 是路由名称,value 是 WidgetBuilder
final Map<String, WidgetBuilder> appRoutes = {
// 原生页面构建
// 'image': (context) => ImagePage(title: "native加载的页面"),
// 改造为热修页面动态加载入口:
// - pageName: "image"
// - defaultWidgetBuilder: 构建原生 ImagePage
// - namedParameters: 传递给热修页面的命名参数
'image': (context) => ConchLoaderAPI.load(
"image",
(_) => ImagePage(title: "native加载的页面"),
namedParameters: {"title": "热修加载的页面"},
),
// 改造为热修页面动态加载入口:
// - pageName: "list"
// - defaultWidgetBuilder: 构建原生 ListPage
// - positionalParameters: 传递给热修页面的位置参数
'list': (context) => ConchLoaderAPI.load(
"list",
(_) => ListPage("native参数1", "native参数2", "native参数3"),
positionalParameters: ["热修参数1", "热修参数2", "热修参数3"],
),
// 其他页面直接返回原生页面
'anim': (context) => AnimationPage(),
};
//三、GetX 路由结合onchLoaderAPI.load 实现热修页面动态加载
final List<GetPage> getPages = [
// 纯原生页面入口
GetPage(
name: 'MyHomePage',
page: () => MyHomePage(key: myHomePageKey, title: '主页面'),
),
// 改造为使用 ConchLoaderAPI.load 接入动态加载机制,
GetPage(
name: 'image',
page: () => ConchLoaderAPI.load(
"image", // 页面标识,对应补丁映射
(_) => ImagePage(title: "native加载的页面"),
namedParameters: {"title": "热修加载的页面"}, // 补丁指定参数
),
),
// 改造为动态加载 ListPage,支持补丁替换及参数传递
GetPage(
name: 'list',
page: () => ConchLoaderAPI.load(
"list",
(_) => ListPage("native参数1", "native参数2", "native参数3"),
positionalParameters: ["热修参数1", "热修参数2", "热修参数3"],
),
),
// 其它原生页面,无动态补丁需求可直接写
GetPage(name: 'anim', page: () => AnimationPage()),
GetPage(name: 'touch', page: () => TouchPage()),
GetPage(name: 'loop', page: () => LoopPage()),
];
总结
页面热更接入主要两步:
- 新增配置页面映射表并用
@ConfigGenerate()注解,生成页面入口信息。 - 用
ConchLoaderAPI.load替换页面创建逻辑,实现动态加载。如果是其他路由框架,可参考以上样例利用ConchLoaderAPI.load方法自行接入热更机制。
五、编译基准包
- 编译基准包:完成SDK接入和页面热更改造后,使用 Conch-Flutter 编译生成一个 Release 产物。这个产物即为基准包,用于正式发布给用户。
- 生成符号文件:Conch在编译生成产物的同时,会在
.dart_tool/conch_build目录下自动生成一个名为conch_base_<versionCode>.json的符号文件。 请务必妥善保存每个基准包对应的符号文件,该符号文件在后续编译该基准包的补丁时提供必要的基准信息,将符号文件归档保存。

六、补丁制作
Conch 提供了多种粒度的热修能力,并通过相关注解,帮助开发者灵活标记补丁范围。在完成SDK接入,改造项目以支持页面级动态化以及编译出基准包后,即可根据具体业务场景需要,对函数或者类进行完善和修复并加上 @PatchOnly 注解,最后进入补丁制作环节。这一节将详细介绍补丁制作流程。
6.1 修复业务代码
6.1.1 函数热修复(hotfix 模式支持)
- 适用场景
- 仅需修复某个函数的小 bug,无需整体替换页面或类。
- 代码变动范围小,风险低,补丁包体积小,发布更高效。
- 使用方法
在需要热修复的函数方法声明前添加
@PatchOnly注解,然后直接修改该函数的代码实现。修复后,打包生成补丁包并发布。
无需修改页面或路由结构,只需保证应用启动时尽早加载补丁即可,例如:
// 仅对该函数修复,其他部分完全不受影响
()
void myBugFixFunction() {
// 修复后的新实现
}
注意: 补丁包正确加载后,函数的最新实现才能生效。请确保补丁的及时加载。 加载补丁方法
// 建议在应用启动时初始化,保证补丁尽早生效
ConchLoaderAPI.getPatchLoadResult(preload: true);
6.1.2 页面与函数热更(all&hotfix 模式)
- 改造前提
- 必须在基准包中,先完成“页面与函数热更改造流程”(详见4.1节),确保:
- 目标页面已注册进页面映射表。
- 页面入口已替换为
ConchLoaderAPI.load方法进行实例化和加载。
- 使用方法
对需要热更新的页面类,在类声明前添加
@PatchOnly注解,并进行所需的业务修复。完成改动后,打包生成并发布补丁包。
// 对整个页面类进行热更,只需加注解并修复逻辑
()
class ImagePage extends StatelessWidget {
// 页面实现
}
- 注意事项
- 只有经过上述改造后的页面,才能支持通过此模式进行完整页面类的热更新。
- 未做基准包改造的页面,无法通过此机制实现类级别热更新。
PS:仅对需要修复的类或页面添加 @PatchOnly 注解,避免无关代码被打入补丁,减小补丁体积。
6.2 编译补丁包
6.2.1 配置目标版本
首先,我们需要将基准包符号文件放到 conch_base 目录下,并将 Conch 配置中的 targetBaseVersions 字段设置为基准包版本(appVersion)。
例如:我们将对 1.0.0 版本构建一个补丁,为便于区分和理解将versionCode设置为 1.0.1+1,那我们将进行如下所示的配置,__同时将 conch_base_1.0.0.json 这个符号文件放到 conch_base 目录下。
conch:
enable: true
versionCode: 1.0.1+1
targetBaseVersions: 1.0.0
conchMode: all&hotfix
licensePath: ./conch_license
6.2.2 生成补丁产物
完成业务代码的修改以及相关配置后,再次触发Flutter的Release产物构建,则会在 .dart_tool/conch_build/patch_zip/ 下生成补丁包conch_result.zip 以及符号文件conch_base_1.0.1.json ,依据需要选择是否对该符号文件进行归档。
没有将基准包的符号文件拷贝到
conch_base目录下,或者在conch_base中没有对应的conch_base_<targetBaseVersions>.json符号文件,对应版本的的补丁都会构建失败。补丁制作整个过程都需要在Release模式下进行,Debug不支持。

获取到补丁包后,即可将该补丁包配置到shiply发布平台进行发布,并由SDK自动下载安装,并在合适的时机加载生效。
发布平台的使用可参考《平台使用指引》
七、Module的形式集成Conch
在开始Module集成之前,请确保已完成以下准备工作:
- 已完成前述章节中的SDK接入配置
- 已正确配置Conch依赖
本节将以已集成Conch的example_external_module项目为示例,详细介绍如何在iOS和Android端以Module形式进行集成,整体项目结构如下:
root/
├── example_external_module/ # Conch Module项目,已完成Conch集成配置
├── example_ios_module_host/ # iOS宿主应用示例项目
└── example_module_host_android/ # Android宿主应用示例项目
7.1. 配置Conch Module的pubspec.yaml
在已完成SDK接入和Conch依赖配置的基础上,需要在pubspec.yaml中添加Module相关配置,使项目能够以Module形式被原生应用集成。
# 增加关键配置:标识这是一个Flutter Module
flutter:
module:
androidX: true
androidPackage: com.example.example_external_module
iosBundleIdentifier: com.example.exampleExternalModule
配置说明:
androidX: true:启用AndroidX支持,确保与现代Android项目兼容androidPackage:指定Android平台的包名,需与宿主应用保持一致的命名规范iosBundleIdentifier:指定iOS平台的Bundle标识符
7.2 iOS/Android端集成
7.2.1 iOS端集成
1、CocoaPods方式集成
配置iOS宿主应用Podfile
在iOS宿主项目的Podfile文件中添加Flutter Module的集成配置:
# Conch Module项目相对路径(根据实际情况调整)
flutter_application_path = '../example_external_module'
# 加载Flutter的podhelper
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
target 'YourAppTargetName' do # 替换为你的 iOS 项目 Target 名称
# ... 其他 Pods ...
install_all_flutter_pods(flutter_application_path)
end
post_install do |installer|
flutter_post_install(installer) if defined?(flutter_post_install)
end
配置说明:
flutter_application_path:指定Flutter Module项目的相对路径,根据实际项目结构调整install_all_flutter_pods:自动安装Flutter Module的所有依赖flutter_post_install:执行Flutter特定的后安装配置
注意事项:
- 确保Flutter Module项目已正确配置
pubspec.yaml中的Module配置 - 如果Flutter Module使用了本地路径依赖,需要在Podfile中额外配置相关路径
- 首次集成时建议先执行
pod install验证配置是否正确
iOS构建流程
# 1. 构建Flutter Module为iOS Framework
cd example_external_module
flutter clean
flutter pub get
flutter build ios-framework --no-color
# 2. 安装iOS应用依赖
cd ../example_ios_module_host
pod install
# 3. 构建iOS应用
7.2.2 Android端集成
Flutter Android 项目通常会从 Google Maven 仓库 (google()) 和 Maven Central (mavenCentral()) 获取其依赖。
为了确保项目能够正确构建并使用 Conch 的热修能力,我们需要在项目的 build.gradle 文件中配置额外的本地Conch引擎仓库以及添加Shiply仓库。
配置Android宿主应用settings.gradle.kt
在Android宿主项目的settings.gradle.kts文件中添加必要的仓库配置:
特别注意:需要添加Conch引擎仓库和Shiply仓库,否则可能无法获取Conch相关依赖。
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
// 添加Flutter AAR本地仓库路径
maven { url = uri("${rootDir}/../example_external_module/build/host/outputs/repo") }
// 添加Conch引擎仓库
// 历史版本:通过zip包分发的ConchSDK,需配置本地路径依赖(请替换为实际路径)
// maven { url = uri("{YOUR_PATH}/conch-flutter/bin/conch/maven") }
// 新版本:通过git仓库分发的Conch-FlutterSDK,支持Maven制品库
maven { url = uri("https://maven.cnb.cool/tencent-tds/conch-release-maven/-/packages/") }
// 添加Shiply仓库(重点注意)
maven { url = uri("https://maven.cnb.cool/tencent-tds/shiply-public/-/packages/") }
}
}
配置app/build.gradle.kts
在应用模块的build.gradle.kts文件中添加Flutter AAR依赖:
dependencies {
// 添加Flutter AAR依赖
implementation("com.example.example_external_module:flutter_release:1.0")
// 其他现有依赖
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
// ...
}
Android构建流程
# 1. 构建Flutter Module为AAR
cd example_external_module
flutter clean
flutter pub get
flutter build --no-color aar
# 2. 构建Android应用
cd ../example_module_host_android
./gradlew assembleRelease
八、 常见问题及解决方案
文档参考:查阅FAQ文档获取常见问题解答