Smart Assets Plugin
智能资源下载插件 - 支持图片压缩、远端下载、智能切换、增量更新、分块下载的 Flutter 资源优化方案。
特性
✅ 包体积优化: 压缩图片减小 70-80% 体积
✅ 智能下载: ZIP 包下载或增量更新,自动选择最优方案
✅ 智能切换: 自动使用高清资源,降级到压缩资源
✅ 增量更新: 基于文件哈希的增量更新,节省流量
✅ 分块下载: 按优先级分组下载,大文件分片下载
✅ 断点续传: 大文件支持断点续传,避免重复下载
✅ 通用加载器: 灵活的通用加载器,支持任意类型资源
快速开始
1. 安装依赖
dependencies:
smart_assets_plugin:
path: sdk/smart_assets_plugin
2. 初始化配置
dart run smart_assets_plugin:init_config
编辑生成的 smart_assets_config.yaml 配置文件。
3. 构建资源
# 增量构建(默认,只处理变化的文件)
dart run smart_assets_plugin:build_all
# 全量构建(重新处理所有文件)
dart run smart_assets_plugin:build_all --full
4. 初始化插件
import 'package:smart_assets_plugin/smart_assets_plugin.dart';
import 'package:your_app/core/assets/generated_assets.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await SmartAssetsPlugin.initialize(
config: GeneratedAssets.config,
autoDownload: true,
);
runApp(MyApp());
}
使用示例
3.1 基本使用
最简单的图片加载:
SmartAssetImage(
assetPath: 'assets/icons/home.png',
resolver: SmartAssetsPlugin.instance.resolver,
width: 100,
height: 100,
)
3.2 高阶使用
高清资源自动下载
在 manifest.json 中配置高清资源:
{
"assets": [
{
"path": "icons/home.png",
"hdUrl": "https://cdn.example.com/hd/icons/home.png",
"hdAutoDownload": true
}
]
}
使用组件(自动从 manifest 读取配置):
SmartAssetImage(
assetPath: 'assets/icons/home.png',
resolver: SmartAssetsPlugin.instance.resolver,
width: 100,
height: 100,
fit: BoxFit.cover,
placeholder: CircularProgressIndicator(),
errorWidget: Icon(Icons.error),
)
状态监听
final plugin = SmartAssetsPlugin.instance;
// 监听下载状态
plugin.downloadStatus.addListener(() {
final status = plugin.downloadStatus.value;
print('下载状态: $status');
});
增量更新
final plugin = SmartAssetsPlugin.instance;
// 检查是否有更新
final hasUpdate = await plugin.checkForIncrementalUpdate();
if (hasUpdate) {
// 执行增量更新
await plugin.performIncrementalUpdate(
onProgress: (phase, progress, description) {
print('[$phase] ${(progress * 100).toStringAsFixed(1)}%');
},
);
}
通用资源加载器
// 加载 JSON 文件
SmartAssetLoader<Map<String, dynamic>>(
assetPath: 'assets/data/config.json',
resolver: SmartAssetsPlugin.instance.resolver,
loader: (resolvedPath) async {
final text = await SmartAssetsPlugin.instance.resolver
.loadString('assets/data/config.json');
return jsonDecode(text) as Map<String, dynamic>;
},
builder: (context, data) {
return Text('Version: ${data['version']}');
},
placeholder: CircularProgressIndicator(),
errorWidget: Icon(Icons.error),
)
3.3 全部参数
SmartAssetImage 完整参数
SmartAssetImage(
// 必需参数
assetPath: 'assets/icons/home.png',
resolver: SmartAssetsPlugin.instance.resolver,
// 尺寸参数
width: 100.0,
height: 100.0,
fit: BoxFit.cover,
scale: 1.0,
// 样式参数
color: Colors.blue,
colorBlendMode: BlendMode.srcIn,
alignment: Alignment.center,
repeat: ImageRepeat.noRepeat,
// UI 参数
placeholder: CircularProgressIndicator(),
errorWidget: Icon(Icons.error),
fadeDuration: Duration(milliseconds: 300),
// 配置参数
uiConfig: UIConfig(
showDownloadProgress: true,
showDownloadError: true,
),
)
参数说明:
assetPath(String, 必需): 资源路径,如'assets/icons/home.png'resolver(SmartAssetsResolver, 必需): 资源解析器,使用SmartAssetsPlugin.instance.resolverwidth(double?, 可选): 图片宽度height(double?, 可选): 图片高度fit(BoxFit?, 可选): 图片适配方式scale(double, 可选): 图片缩放比例,默认1.0color(Color?, 可选): 图片颜色混合colorBlendMode(BlendMode?, 可选): 颜色混合模式alignment(AlignmentGeometry, 可选): 对齐方式,默认Alignment.centerrepeat(ImageRepeat, 可选): 重复方式,默认ImageRepeat.noRepeatplaceholder(Widget?, 可选): 加载占位符errorWidget(Widget?, 可选): 错误占位符fadeDuration(Duration?, 可选): 淡入淡出动画时长uiConfig(UIConfig?, 可选): UI 配置
SmartAssetLoader 完整参数
SmartAssetLoader<T>(
// 必需参数
assetPath: 'assets/data/config.json',
resolver: SmartAssetsPlugin.instance.resolver,
loader: (resolvedPath) async {
// 加载资源的异步函数
final bytes = await resolver.loadBytes(assetPath);
return parseData(bytes);
},
builder: (context, data) {
// 构建 UI 的函数
return Widget(data);
},
// UI 参数
placeholder: CircularProgressIndicator(),
errorWidget: Icon(Icons.error),
// 配置参数
uiConfig: UIConfig(
showDownloadProgress: true,
showDownloadError: true,
),
)
参数说明:
assetPath(String, 必需): 资源路径resolver(SmartAssetsResolver, 必需): 资源解析器loader(Futurebuilder(Widget Function(BuildContext, T), 必需): 构建 UI 的函数placeholder(Widget?, 可选): 加载占位符errorWidget(Widget?, 可选): 错误占位符uiConfig(UIConfig?, 可选): UI 配置
完整配置示例
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await SmartAssetsPlugin.initialize(
config: GeneratedAssets.config,
autoDownload: true,
loggingConfig: const LoggingConfig(
enabled: true,
level: 'debug',
prefix: '[SmartAssets]',
),
);
runApp(MyApp());
}
构建脚本
build_all - 一键构建(推荐)
执行完整的资源构建流程。
使用方式:
# 增量构建(默认,只处理变化的文件)
dart run smart_assets_plugin:build_all
# 全量构建(重新处理所有文件)
dart run smart_assets_plugin:build_all --full
# 或
dart run smart_assets_plugin:build_all -f
执行步骤:
- 压缩图片资源(备份到
assets_backup/) - 生成常量文件(
lib/core/assets/generated_assets.dart) - 生成 Manifest 文件(
build/assets_release/manifest.json) - 打包 ZIP 文件(
build/assets_release/assets.zip)
参数说明:
--full或-f: 全量构建模式,重新处理所有文件(默认:增量构建)
init_config - 初始化配置
生成配置文件模板。
使用方式:
# 在项目根目录生成配置文件
dart run smart_assets_plugin:init_config
# 指定输出路径
dart run smart_assets_plugin:init_config /path/to/output.yaml
功能:
- 在项目根目录生成
smart_assets_config.yaml - 包含所有配置项的详细说明
- 如果文件已存在,会提示是否覆盖
compress_assets - 压缩资源
单独执行图片压缩。
使用方式:
# 增量压缩(默认,只处理变化的文件)
dart run smart_assets_plugin:compress_assets
# 全量压缩(重新处理所有文件)
dart run smart_assets_plugin:compress_assets --full
# 或
dart run smart_assets_plugin:compress_assets -f
功能:
- 压缩
assets/下的图片资源 - 原始图片备份到
assets_backup/ - 生成
assets_mapping.json资源映射文件 - 支持增量压缩(只处理变化的文件)
参数说明:
--full或-f: 全量压缩模式,重新处理所有文件(默认:增量压缩)
generate_constants - 生成常量
生成资源路径常量文件。
使用方式:
dart run smart_assets_plugin:generate_constants
功能:
- 生成
lib/core/assets/generated_assets.dart - 包含所有资源路径常量
- 包含运行时配置对象(
GeneratedAssets.config) - 包含内置资源和远程资源集合
generate_manifest - 生成清单
生成资源清单文件。
使用方式:
# 增量模式(默认,合并现有 manifest)
dart run smart_assets_plugin:generate_manifest
# 全量模式(重新生成 manifest)
dart run smart_assets_plugin:generate_manifest --full
# 或
dart run smart_assets_plugin:generate_manifest -f
# 显式指定增量模式
dart run smart_assets_plugin:generate_manifest --incremental
# 或
dart run smart_assets_plugin:generate_manifest -i
功能:
- 生成
build/assets_release/manifest.json - 包含所有资源的路径、哈希、大小等信息
- 支持增量模式(合并现有 manifest,保留手动配置)
- 支持高清资源配置(
hdUrl,hdAutoDownload)
参数说明:
--full或-f: 全量模式,重新生成 manifest(默认:增量模式)--incremental或-i: 增量模式,合并现有 manifest
generate_zip - 打包ZIP
打包资源为 ZIP 文件。
使用方式:
dart run smart_assets_plugin:generate_zip
功能:
- 将
assets_backup/下的资源打包成 ZIP 文件 - 输出到
build/assets_release/assets.zip - 显示打包进度和统计信息
restore_assets - 还原资源
从备份目录还原原始资源。
使用方式:
# 交互式还原(需要确认)
dart run smart_assets_plugin:restore_assets
# 强制还原(不需要确认)
dart run smart_assets_plugin:restore_assets --force
# 或
dart run smart_assets_plugin:restore_assets -f
功能:
- 从
assets_backup/还原所有原始文件到assets/ - 覆盖压缩后的文件
- 显示还原进度和统计信息
参数说明:
--force或-f: 强制还原,不需要确认(默认:交互式确认)
注意:还原操作会覆盖当前 assets 目录中的压缩文件,建议在提交代码前使用。
replace_image_usage - 替换图片使用
自动替换项目中的 Image.asset() 和 AssetImage() 为插件组件。
使用方式:
# 交互式替换
dart run smart_assets_plugin:replace_image_usage
# 预览模式(不实际修改)
dart run smart_assets_plugin:replace_image_usage --dry-run
# 或
dart run smart_assets_plugin:replace_image_usage -d
功能:
- 扫描指定文件夹下的所有
.dart文件 - 自动替换
Image.asset()→SmartAssetImage - 自动替换
AssetImage()→SmartAssetImageProvider - 自动添加必要的 import 语句
参数说明:
--dry-run或-d: 预览模式,不实际修改文件(默认:交互式替换)
替换示例:
// 替换前
Image.asset('assets/icons/home.png', width: 100, height: 100)
// 替换后
SmartAssetImage(
assetPath: 'assets/icons/home.png',
resolver: SmartAssetsPlugin.instance.resolver,
width: 100,
height: 100,
)
配置说明
配置文件结构
主要配置项(smart_assets_config.yaml):
# 基础配置
enabled: true
version: "1.0.0"
# 远端配置
remote:
base_url: "https://cdn.example.com/assets/"
zip_name: "assets.zip"
timeout: 300
auto_download_on_wifi: true
# 资源分类
assets:
builtin: # 内置资源(保留在assets,同时打包到ZIP)
- "audio/**"
- "videos/**"
remote: # 远程资源(从assets删除,仅打包到ZIP)
- "icons/**"
- "images/**"
target_dirs: # 压缩目标目录
- "icons"
- "images"
# 增量更新
incremental:
enabled: true
cache_manifest_locally: true
# 分块下载
chunked_download:
enabled: true
chunk_threshold_mb: 10
chunk_size_mb: 2
enable_breakpoint_resume: true
# 优先级配置
priority:
download_critical_first: true
background_download_others: true
# 压缩配置
compression:
quality: 30
scale_ratio: 0.8
skip_size_kb: 50
skip_extensions:
- ".gif"
- ".webp"
# 本地存储配置
storage:
download_dir: "downloaded_assets"
backup_dir: "assets_backup"
mapping_file: "assets_mapping.json"
hd_download_dir: "downloaded_assets_hd"
# 下载策略配置
download:
max_retries: 3
retry_delay_base: 2
verify_integrity: true
progress_callback_interval: 500
# 资源信息管理配置
asset_info:
url: "https://cdn.example.com/assets/info.json"
method: "json"
post_data: ""
# 脚本配置
scripts:
output_dir: "build/assets_release"
constants_file: "lib/core/assets/generated_assets.dart"
高清资源配置
高清资源配置在 manifest.json 中,每个资源项可以配置:
{
"assets": [
{
"path": "icons/home.png",
"hash": "sha256:xxx",
"size": 1024,
"priority": "important",
"builtin": true,
"hdUrl": "https://cdn.example.com/hd/icons/home.png",
"hdAutoDownload": true,
"hdVersion": "1.0.0"
}
]
}
配置说明:
hdUrl(String, 可选): 高清资源 URLhdAutoDownload(bool, 可选): 是否自动下载高清资源,默认truehdVersion(String, 可选): 高清资源版本号
使用方式:
- UI 组件自动从 manifest 读取配置,无需手动传参
- 如果配置了
hdUrl且hdAutoDownload为true,组件会自动在后台下载高清资源 - 下载完成后,组件会自动切换到高清资源显示
资源配置说明
builtin 和 remote 资源的区别
- builtin(内置资源):保留在
assets/目录,同时打包到 ZIP。运行时优先检查是否有下载的版本,支持热更新。适合音频、视频、字体等。 - remote(远程资源):从
assets/目录删除,仅打包到 ZIP。必须下载后才能使用。适合图片、图标等可以压缩的资源。
API 文档
SmartAssetsPlugin
主插件类,提供统一的入口。
初始化
await SmartAssetsPlugin.initialize(
config: GeneratedAssets.config,
autoDownload: true,
loggingConfig: LoggingConfig(
enabled: true,
level: 'debug',
prefix: '[SmartAssets]',
),
);
ZIP 包下载
final plugin = SmartAssetsPlugin.instance;
// 开始下载
await plugin.startDownload();
// 取消下载
await plugin.cancelDownload();
增量更新
final plugin = SmartAssetsPlugin.instance;
// 检查是否有更新
final hasUpdate = await plugin.checkForIncrementalUpdate();
// 执行增量更新
await plugin.performIncrementalUpdate(
onProgress: (phase, progress, description) {
print('[$phase] ${(progress * 100).toStringAsFixed(1)}%');
},
);
状态监听
final plugin = SmartAssetsPlugin.instance;
// 监听下载状态
plugin.downloadStatus.addListener(() {
final status = plugin.downloadStatus.value;
print('下载状态: $status');
});
智能组件
SmartAssetImage
智能图片组件,自动从 manifest 读取高清资源配置。
SmartAssetImage(
assetPath: 'assets/icons/home.png',
resolver: SmartAssetsPlugin.instance.resolver,
width: 100,
height: 100,
)
SmartAssetImageProvider
图片 Provider,支持在任何需要 ImageProvider 的地方使用。
DecorationImage(
image: SmartAssetImageProvider(
assetPath: 'assets/icons/home.png',
resolver: SmartAssetsPlugin.instance.resolver,
scale: 1.0,
),
)
SmartAssetLoader
通用资源加载器,支持任意类型资源。
SmartAssetLoader<Map<String, dynamic>>(
assetPath: 'assets/data/config.json',
resolver: SmartAssetsPlugin.instance.resolver,
loader: (resolvedPath) async {
final text = await resolver.loadString(assetPath);
return jsonDecode(text) as Map<String, dynamic>;
},
builder: (context, data) {
return Text('Version: ${data['version']}');
},
)
核心 API
SmartAssetsResolver
资源解析器,提供资源加载和解析功能。
final resolver = SmartAssetsPlugin.instance.resolver;
// 加载字节数据
final bytes = await resolver.loadBytes('assets/icons/home.png');
// 加载文本数据
final text = await resolver.loadString('assets/data/config.json');
// 解析资源路径
final resolvedPath = await resolver.resolveAssetPath('assets/icons/home.png');
// 获取高清资源 URL
final hdUrl = resolver.getHdUrl('assets/icons/home.png');
// 获取是否自动下载高清资源
final autoDownload = resolver.getHdAutoDownload('assets/icons/home.png');
发布流程
1. 构建资源
dart run smart_assets_plugin:build_all
2. 上传到 CDN
上传以下文件到 CDN:
build/assets_release/assets.zip- 资源包build/assets_release/manifest.json- Manifest 文件
示例(阿里云 OSS):
ossutil cp build/assets_release/assets.zip \
oss://your-bucket/assets/assets.zip \
--acl public-read
ossutil cp build/assets_release/manifest.json \
oss://your-bucket/assets/manifest.json \
--acl public-read
3. 配置 CDN URL
在 smart_assets_config.yaml 中配置 CDN URL:
remote:
base_url: "https://cdn.example.com/assets/"
zip_name: "assets.zip"
常见问题
Q: 如何选择 ZIP 包下载还是增量更新?
A:
- 首次安装: 自动使用 ZIP 包下载(全量)
- 版本更新: 如果启用了增量更新,自动使用增量更新
- 降级方案: 增量更新失败会自动降级到 ZIP 包下载
Q: builtin 和 remote 资源的区别?
A:
- builtin(内置资源):保留在
assets/目录,同时打包到 ZIP。运行时优先检查是否有下载的版本,支持热更新。适合音频、视频、字体等。 - remote(远程资源):从
assets/目录删除,仅打包到 ZIP。必须下载后才能使用。适合图片、图标等可以压缩的资源。
Q: 如何配置高清资源?
A:
- 高清资源配置在
manifest.json中,每个资源项可以配置hdUrl和hdAutoDownload - UI 组件会自动从 manifest 读取配置,无需手动传参
- 如果配置了
hdUrl且hdAutoDownload为true,组件会在后台自动下载高清资源 - 下载完成后,组件会自动切换到高清资源显示
Q: SmartAssetLoader 的 builder 为什么 data 可能为 null?
A:
- 资源加载失败时,
loader函数可能返回null或抛出异常 - 开发者需要在
builder中判断data == null,提供合适的错误提示 - 这样设计是为了给开发者更灵活的错误处理能力
Q: 如何自定义加载占位符和错误提示?
A:
SmartAssetImage和SmartAssetLoader都支持placeholder和errorWidget参数- 可以传入自定义的 Widget 来替换默认的占位符和错误提示
SmartAssetImage(
assetPath: 'assets/icons/home.png',
resolver: SmartAssetsPlugin.instance.resolver,
placeholder: CircularProgressIndicator(),
errorWidget: Icon(Icons.error),
)
许可证
MIT License
贡献
欢迎提交 Issue 和 Pull Request!
Libraries
- smart_assets_plugin
- Smart Assets Plugin - 智能资源下载插件