Skip to main content

Shiply Flutter 远程资源 SDK 集成

一、隐私安全说明

Shiply 资源发布 Flutter SDK
版本:0.0.13
更新时间:2025年2月14日
SDK介绍:为移动开发者提供专业的资源分发能力,帮助开发者动态下载远程资源文件。
服务提供方:深圳市腾讯计算机系统有限公司
隐私保护规则:《Shiply资源发布SDK个人信息保护规则》
合规使用指南:《Shiply资源SDK合规使用指南》

前置概念:接入前请先阅读 通用概念,了解各平台共用的 appId/appKey/deviceId/userId/target/资源加载策略 等核心概念,避免跨平台混淆。

二、SDK 接入

reshub_flutter SDK 发布在 pub.dev:reshub_flutter | Flutter package

2.1 配置依赖

在 Flutter 工程中的 pubspec.yaml 中添加 reshub_flutter 的依赖:

dependencies:
reshub_flutter: 0.0.13

在代码中导入插件接口:

import 'package:reshub_flutter/reshub_flutter.dart';

iOS 需要在 Target 的 Build Settings 中设置 Allow Non-modular Incudes In Framework Modules = YES

2.2 初始化 reshub

具体例子可以参考 example/lib/main.dart

2.2.1 在 dart 层初始化 ReshubCenter

String deviceId = "device123";
String appVersion = "1.2.3";
// 是否是 debug 包
bool isDebugPackage = false;
Map<String, String> params = Map();
params["testKey"] = "testValue";
ReshubFlutter.initReshubCenter(deviceId, appVersion, isDebugPackage, params);
if (Platform.isIOS) {
ReshubFlutter.initReshub("14e1a90fcd", "d96d3d4a-fe58-4b8d-99c4-61d894a3d3bb", "online");
} else if(Platform.isAndroid) {
ReshubFlutter.initReshub("9d256c9ecc", "bfe91841-af1a-4572-9868-8b3c70a8d19c", "online");
}

2.2.2 在 dart 层初始化 reshub 实例

ReshubFlutter reshubInstance = ReshubFlutter();

2.2.3 Navtive 层设置

Android 避免重复初始化

组件的初始化调用,需要结合具体业务场景来考虑: 组件本身设计为单例模式,多次调用,只会生效一次。 在混合工程中,如果 Native 侧已经对 Reshub 组件进行过初始化,对于 Android 平台,需要在 Native 初始化 Reshub 组件的代码处额外调用:

ReshubHostApiImpl.markHasInitReshubCenter()
iOS 避免重复初始化
[[ReshubHostApiImpl sharedInstance] markHasInitReshubCenter];
Android 对接日志实现

如果是混合工程,并且Native 侧已经设置过 Reshub 组件日志实现,可以不用再额外设置; 如果Native 侧没有设置过 Reshub 组件日志实现,需要在 dart 层初始化 ReshubCenter 之前,先设置好日志实现类:

ReshubHostApiImpl.setLogDelegate(log: IRLog)
iOS 对接日志实现
  • 接出日志,需要实现 RaftInterface 标准里的 RAFTLogProtocol 协议

    # 复制 RDelivery 的 RDLoggerImpl 文件,将 NSLog 一行换成App中打印日志的函数即可。
    https://git.woa.com/RDelivery/Core/rdelivery-ios/blob/master/RDelivery/DefaultInjectImpl/Log/RDLoggerImpl.m
  • 替换成自己日志实现,完成日志接出

    @interface CustomDependImpl : ResHubDependImpl
    @end

    @implementation CustomDependImpl
    + (instancetype)defaultDepends {
    CustomDependImpl *depend = [super defaultDepends];
    // ResHubDependImpl 下的所有组件,都可以替换成你的实现,以日志组件为例
    depend.logImpl = [CustomLogImpl sharedInstance];
    return depend;
    }
    @end
  • 依赖注入到 ResHub

    - (void)injectReshubDependImpl {
    CustomDependImpl *depend = [CustomDependImpl defaultDepends];
    [[ReshubHostApiImpl sharedInstance] injectDependImpl:depend];
    }

2.3 使用 reshub 实例加载资源

// 业务方在 shiply 前端页面创建的资源 key 名字
String resId = "test_res_key";

// 获取资源 key 的锁定版本,同一个进程内多次调用都返回同一个版本
reshubInstance.get(resId).then(
(value) => printText("get result => path: ${value.localPath} "));

// 获取资源 key 的最新版本,同一个进程内多次调用可能返回不同版本,比如使用过程中从 server 拉取到了更高的版本,则会返回高版本
reshubInstance.getLatest(resId).then(
(value) => printText("getLatest result => path: ${value.localPath} "));

// 加载资源 key 的本地版本,同一个进程内多次调用都返回同一个版本,这个方法会异步尝试下载更高版本的资源
reshubInstance.load(resId).then(
(value) => printText("load result => isSuccess: ${value.isSuccess} "
"path: ${value.resModel?.localPath},originLocalPath: ${value.resModel?.originLocalPath}"));

// 加载资源 key 的最新版本,这个方法会同步尝试下载更高版本的资源
reshubInstance.loadLatest(resId).then(
(value) => printText("loadLatest result => isSuccess: ${value.isSuccess} path: ${value.resModel?.localPath}"));

// 加载资源 key 的最新版本,可控制是否强制请求远程配置
reshubInstance.loadLatestWithOption(resId, true).then(
(value) => printText("loadLatestWithOption result => isSuccess: ${value.isSuccess} path: ${value.resModel?.localPath}"));

三、能力限制说明

适用版本:以下限制适用于当前最新版本 v0.0.24(pubspec.yaml)及之前所有版本。未来版本可能会补齐部分能力,届时请以最新 CHANGELOG 为准。

不支持的监听机制

Flutter Wrapper 使用 Pigeon 的 fire-and-forget + request-reply 模式,当前 pigeon 定义中没有任何 @FlutterApi() 回调接口,因此 Native 端无法主动回调 Flutter 端,所有事件监听均不可用。

原生能力Flutter 支持(v0.0.24)
onResFirstLoaded 监听❌ 不支持
onResRefreshed 监听❌ 不支持
onResConfigInfoPullTypeAllFinished 监听❌ 不支持
下载进度回调(progress)❌ 不支持(iOS 端 progress 参数硬编码为 nil,Android 端未实现 onProgress
ResHubResRefreshListener 协议❌ 无对应实现

不支持的能力

能力Flutter 支持(v0.0.24)
getStatus / 资源状态查询❌ 不支持
delete / 删除资源❌ 不支持
资源清理❌ 不支持
批量操作(batchLoadWithIds❌ 不支持,需逐个调用
updateAllConfigs / updateConfigWithKeys 等配置拉取❌ 未通过 Flutter Wrapper 暴露

以上 7 项能力在 Dart 层和 iOS/Android Native 层均无任何实现痕迹,属于架构层面的缺失(pigeon 接口未定义),而非"有接口但未实现"。

需要这些能力时

必须直接调用原生 ResHub API:

  • iOS:ResHubModel.status[resHub deleteWithId:][resHub updateAllConfigsWithCompleted:]
  • Android:ResHubModel.statusreshub.delete(resId)reshub.updateAllConfigs()

可通过自定义 MethodChannel 桥接所需方法。

四、注意事项

  1. 两步初始化:先 initReshubCenter(设备/版本参数),再 initReshub(凭证),顺序不能反。
  2. 依赖原生 SDK:Flutter 层是 MethodChannel 桥接,宿主 iOS/Android 必须已接入 ResHub 原生 SDK。
    • iOS:必须安装 ResHub pod 并在 Flutter initReshubCenter 调用之前完成原生 [ResHubCenter initSDK:] 初始化
    • Android:必须添加 reshub gradle 依赖并在 Flutter initReshubCenter 调用之前完成原生 ResHubCenter.init() 初始化
    • 违反顺序会抛出 PlatformException,错误信息为 "channel not found"
  3. env 字符串initReshub 的 env 是环境标识字符串。
  4. customParams:自定义参数 Map,用于规则匹配。
  5. Demo:参考 example/ 下最小集成。
  6. 无事件监听:Flutter Wrapper 不提供资源状态变更监听,如需监听资源刷新,必须自行在原生层实现并通过 EventChannel 桥接到 Flutter 层。
  7. 无批量操作:不支持批量加载(batchLoadWithIds),需逐个调用 load / get

五、线程说明

行为
Flutter 层调用所有调用返回 Future<T>,为 async 操作
Pigeon 响应回调所有响应调度到 Flutter 平台(UI)线程
原生侧操作下载、MD5 校验等自动在后台线程执行
手动线程管理Flutter 层无需手动管理线程

六、上报

reshub.reportBusinessEvent(
eventName,
cost, // 耗时
errCode, // 错误码
extInfo, // Map<String,String>
reportImmediately,
);

七、错误处理

所有异步操作通过 LoadResult 判断成功/失败:

try {
final result = await reshub.load(resId);
if (!(result.isSuccess ?? false)) {
print('Load failed: ${result.error?.msg}');
}
} on PlatformException catch (e) {
print('Platform error: ${e.message}');
}

LoadError 结构:

  • code: 错误码(int)
  • msg: 错误描述(String)

PlatformException 在 MethodChannel 返回 error 时抛出,通常表示通道通信层面的问题(如原生 SDK 未初始化)。

八、预置资源

Flutter Wrapper 通过原生层支持预置资源:

  • 预置资源(assets)必须在原生侧(iOS/Android)配置,Flutter Wrapper 没有直接的 localPresetResPath 参数
  • isDebugPackage 控制资源匹配模式(debug 包使用不同资源标识)
  • iOS 侧通过 ResHubParam.localPresetResPath 设置预置资源路径
  • Android 侧通过 ResHubParam.setLocalPresetResPath() 设置
这篇文档对您有帮助吗?