Flutter状态管理方案
经过技术调研和POC验证,最终采用Riverpod + StateNotifier的组合作为核心状态管理方案。选型过程中对比了GetX、BLoC、Provider等多种方案。Riverpod相比GetX提供了更好的类型安全和编译期检查能力;相比BLoC,Riverpod的API更加简洁易用,减少了样板代码量。StateNotifier则提供了清晰的状态变更语义,便于单元测试。
// Riverpod + StateNotifier 状态管理
final userProvider = StateNotifierProvider<UserNotifier, AsyncValue<User>>((ref) {
return UserNotifier(ref.read(userRepositoryProvider));
});
final transactionListProvider = StateNotifierProvider<TransactionNotifier,
AsyncValue<PaginatedList<Transaction>>>((ref) {
return TransactionNotifier(ref.read(transactionRepoProvider));
});
class UserNotifier extends StateNotifier<AsyncValue<User>> {
final UserRepository _repo;
UserNotifier(this._repo) : super(const AsyncValue.loading()) {
_loadUser();
}
Future<void> _loadUser() async {
try {
final user = await _repo.getCurrentUser();
state = AsyncValue.data(user);
} catch (e, st) {
state = AsyncValue.error(e, st);
}
}
Future<void> updateProfile(UserProfile profile) async {
final prev = state;
state = const AsyncValue.loading();
try {
final updated = await _repo.updateProfile(profile);
state = AsyncValue.data(updated);
} catch (e, st) {
state = prev; // 回滚到之前状态
rethrow;
}
}
}
// Widget层消费
class ProfilePage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return ref.watch(userProvider).when(
data: (user) => ProfileContent(user: user),
loading: () => const ShimmerLoading(),
error: (e, _) => ErrorRetryView(
error: e, onRetry: () => ref.invalidate(userProvider)),
);
}
}
💡 状态管理最佳实践
- 按功能模块拆分Provider,避免全局状态臃肿,使用Riverpod的Family和AutoDispose管理生命周期
- 使用AsyncValue统一处理loading/data/error三种状态,避免为每个状态单独写Widget
- 状态变更逻辑集中在Notifier中,Widget只负责展示,遵循单向数据流原则
- 通过ref.watch和ref.listen自动管理依赖关系,实现状态联动更新
离线缓存与数据同步
金融应用需要保证核心数据在弱网或无网环境下可用。我们实现了多层次的缓存策略:L1内存缓存(TTL 5分钟)+ L2本地数据库(Hive + SQLite混合方案)+ L3远程服务器。同时建立自动化的数据同步机制,在网络恢复时自动同步待上传数据。
// 三层缓存核心架构
class ThreeTierCache<T> {
final L1MemoryCache<T> _memory;
final L2DatabaseCache<T> _database;
final L3RemoteSource<T> _remote;
final CachePolicy _policy;
Future<T> get(String key) async {
// L1: 内存缓存(最快)
final cached = _memory.get(key);
if (cached != null) return cached;
// L2: 本地数据库
final local = await _database.get(key);
if (local != null) {
final age = DateTime.now().difference(local.cachedAt);
if (age < _policy.freshDuration) {
_memory.set(key, local.data);
return local.data;
}
// 过期但可用(stale-while-revalidate)
_memory.set(key, local.data);
_remote.fetch(key).then((fresh) {
_database.set(key, fresh);
_memory.set(key, fresh);
});
return local.data;
}
// L3: 远程服务器
final remote = await _remote.fetch(key);
await _database.set(key, remote);
_memory.set(key, remote);
return remote;
}
}
推送通知系统
推送服务采用Firebase Cloud Messaging作为国际版基础通道,同时集成国内厂商推送(华为HMS、小米MiPush、OPPO Push、vivo Push)以保证消息到达率。建立消息分类和优先级机制,确保重要交易通知及时送达。通过服务端消息路由策略,自动选择最优推送通道。
// 推送通知统一管理
class PushManager {
final FirebaseMessaging _fcm = FirebaseMessaging.instance;
final List<PushProvider> _vendorProviders = [];
Future<void> initialize() async {
NotificationSettings settings = await _fcm.requestPermission(
alert: true, badge: true, sound: true, provisional: false,
);
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
final fcmToken = await _fcm.getToken();
await _registerTokens(fcmToken);
}
if (Platform.isAndroid) {
// 按设备厂商初始化对应推送
final vendor = await DeviceInfo.getVendor();
final provider = PushProviderFactory.create(vendor);
if (provider != null) {
await provider.initialize();
_vendorProviders.add(provider);
}
}
_fcm.onTokenRefresh.listen(_registerTokens);
FirebaseMessaging.onMessage.listen(_handleForeground);
FirebaseMessaging.onMessageOpenedApp.listen(_handleTap);
}
void _handleForeground(RemoteMessage msg) {
final notification = AppNotification.fromMap(msg.data);
switch (notification.priority) {
case Priority.critical:
showAlertDialog(notification); // 全屏弹窗
break;
case Priority.high:
showLocalNotification(notification); // 状态栏通知
break;
case Priority.low:
updateBadgeCount(notification); // 静默更新
break;
}
}
}
性能优化实践
针对Flutter应用的性能瓶颈,我们实施了全方位的优化策略,涵盖启动速度、渲染性能、内存管理和包体积优化四个维度。
🚀 启动优化
- 延迟加载非首屏组件,减少main()初始化耗时
- 使用flutter_native_splash实现原生启动页,消除白屏
- 关键数据预加载,并行初始化多个服务
- 延迟初始化第三方SDK(Firebase、Sentry、Analytics等),在首帧渲染后异步初始化
- 使用Isolate进行CPU密集型初始化任务
🎨 渲染优化
- 使用const Widget减少不必要的重建
- 复杂列表使用CustomScrollView + Slivers
- 图片加载使用cached_network_image + 内存缓存
- 动画使用AnimationController避免setState触发全局重建
- 使用RepaintBoundary隔离高频重绘区域
💾 内存优化
- 大图片使用ResizeImage压缩到展示尺寸
- 列表页面退出时主动释放缓存
- 使用WeakReference管理长生命周期对象
- 通过DevTools Memory面板定期分析内存泄漏
- 数据库查询使用分页加载,避免一次性读取大量数据
📦 包体积优化
- 使用--split-debug-info和--obfuscate进行代码混淆和符号分离
- 图片资源使用WebP格式替代PNG,压缩率提升30%
- 移除未使用的国际化资源和字体文件
- 使用deferred components实现功能模块按需加载
- 动态化非核心功能(活动页面、配置页面)通过服务端下发