Flutter 包体积优化详解
简介
应用包体积直接影响用户下载意愿。本文介绍如何优化 Flutter 应用的包体积大小。
分析工具
1. Flutter 分析工具
bash
# 分析 APK
flutter build apk --analyze-size
# 分析 iOS 包
flutter build ios --analyze-size
2. Android Studio
groovy
android {
buildTypes {
release {
// 启用 APK 分析
minifyEnabled true
shrinkResources true
}
}
}
优化方法
1. 资源优化
yaml
# pubspec.yaml
flutter:
assets:
# 只包含必要资源
- assets/images/
- assets/icons/
fonts:
# 只包含使用的字重
- family: Roboto
fonts:
- asset: fonts/Roboto-Regular.ttf
- asset: fonts/Roboto-Bold.ttf
weight: 700
2. 代码优化
dart
// 1. 移除未使用的导入
import 'package:flutter/material.dart';
// import 'package:unused_package/unused.dart'; // 删除
// 2. 使用 const 构造函数
const MyWidget({Key? key}) : super(key: key);
// 3. 延迟加载
late final heavyWidget = FutureBuilder(
future: _loadHeavyWidget(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return snapshot.data as Widget;
}
return CircularProgressIndicator();
},
);
3. 依赖优化
yaml
dependencies:
# 使用精确版本
package_name: 1.0.0
# 使用范围版本
another_package: '>=2.0.0 <3.0.0'
# 按需导入
big_package:
path: packages/big_package
include: ['lib/core.dart']
完整示例
dart
// 1. 图片优化工具
class ImageOptimizer {
static Future<File> optimizeImage(File imageFile) async {
final img = await decodeImageFromList(
await imageFile.readAsBytes(),
);
// 压缩图片
final compressedData = await FlutterImageCompress.compressWithList(
await imageFile.readAsBytes(),
minHeight: 1920,
minWidth: 1080,
quality: 85,
);
// 保存压缩后的图片
final optimizedFile = File(
imageFile.path.replaceAll('.jpg', '_optimized.jpg'),
);
await optimizedFile.writeAsBytes(compressedData);
return optimizedFile;
}
}
// 2. 资源管理器
class AssetManager {
static final Map<String, ImageProvider> _imageCache = {};
static ImageProvider getImage(String name) {
if (_imageCache.containsKey(name)) {
return _imageCache[name]!;
}
final image = AssetImage('assets/images/$name');
_imageCache[name] = image;
return image;
}
static void clearCache() {
_imageCache.clear();
}
}
// 3. 延迟加载管理器
class LazyLoadManager {
static final Map<String, Future<dynamic>> _loadTasks = {};
static Future<T> load<T>(
String key,
Future<T> Function() loader,
) async {
if (_loadTasks.containsKey(key)) {
return await _loadTasks[key] as T;
}
final task = loader();
_loadTasks[key] = task;
return await task;
}
static void clear() {
_loadTasks.clear();
}
}
// 4. 优化后的应用示例
class OptimizedApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// 移除调试标签
debugShowCheckedModeBanner: false,
// 只包含使用的语言
supportedLocales: [
Locale('en', ''),
Locale('zh', ''),
],
// 延迟加载页面
home: FutureBuilder(
future: LazyLoadManager.load(
'home_page',
() => Future.delayed(
Duration(milliseconds: 100),
() => HomePage(),
),
),
builder: (context, snapshot) {
if (snapshot.hasData) {
return snapshot.data as Widget;
}
return SplashScreen();
},
),
);
}
}
打包配置
Android
groovy
android {
buildTypes {
release {
// 启用混淆
minifyEnabled true
// 移除未使用资源
shrinkResources true
// 优化 Dex
proguardFiles getDefaultProguardFile(
'proguard-android-optimize.txt'
),
'proguard-rules.pro'
}
}
// 启用 R8
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
iOS
ruby
# Podfile
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
# 启用 bitcode
config.build_settings['ENABLE_BITCODE'] = 'YES'
# 优化编译
config.build_settings['COMPILER_INDEX_STORE_ENABLE'] = 'NO'
end
end
end
最佳实践
- 优化资源文件
- 移除未使用代码
- 合理使用依赖
- 启用代码压缩
- 实施延迟加载
注意事项
- 保持资源质量
- 测试优化效果
- 监控包大小
- 平衡性能和大小
- 注意兼容性
总结
包体积优化需要从多个方面入手,包括资源优化、代码优化、依赖管理等。通过合理的优化措施,可以显著减小应用的包体积。