Freezed不可变类如何缓存关联Artist对象?求最优方案
解决方法
1. 独立缓存层(最优方案)
既然要避免重复请求API,最合理的方式是把Artist的缓存逻辑从Photo模型中抽离,放到**数据层(比如ArtistRepository)**或专门的缓存类中:
- 在
ArtistRepository里用Map<int, Artist>存储已获取的Artist实例 - 每次调用
getArtist(id)时,先检查缓存:存在则直接返回,不存在再发起API请求,请求成功后写入缓存 - 这样不管哪个页面或功能需要Artist,调用仓库方法时都会自动复用缓存,完全不需要修改Photo模型
示例代码(修改ArtistRepository):
class ArtistRepository { final Map<int, Artist> _artistCache = {}; final ApiClient _apiClient; ArtistRepository(this._apiClient); Future<Artist> getArtist({required int id}) async { // 优先读取缓存 if (_artistCache.containsKey(id)) { return _artistCache[id]!; } // 缓存未命中时请求API final artist = await _apiClient.fetchArtist(id: id); // 写入缓存 _artistCache[id] = artist; return artist; } }
2. 创建组合不可变模型
如果需要在页面间直接传递“Photo+Artist”的组合数据,可以用Freezed封装一个新的不可变类:
@freezed class PhotoWithArtist with _$PhotoWithArtist { factory PhotoWithArtist({ required Photo photo, required Artist artist, }) = _PhotoWithArtist; }
使用时,先通过Photo的artistId获取Artist,再生成这个组合对象,之后在页面和过滤功能中传递该对象即可。
3. 用Freezed Union处理加载状态
如果需要在UI层同步管理“加载中/已加载/加载失败”的状态,可以定义一个Union类型:
@freezed class PhotoArtistState with _$PhotoArtistState { const factory PhotoArtistState.loading(Photo photo) = Loading; const factory PhotoArtistState.loaded(Photo photo, Artist artist) = Loaded; const factory PhotoArtistState.error(Photo photo, String error) = Error; }
在状态管理工具(比如Riverpod、Bloc)中处理异步请求,将状态从Loading切换到Loaded,UI层根据状态渲染即可。
替代库推荐
如果觉得Freezed的不可变约束过于受限,可以考虑:
- built_value:同属不可变模型库,支持更灵活的自定义逻辑(比如延迟加载的计算属性),但需要额外配置代码生成规则
- json_serializable + 手动不可变类:放弃自动生成,手动编写带
copyWith方法的不可变类,完全控制字段和逻辑,适合高度自定义的场景
内容的提问来源于stack exchange,提问作者Stelios Papamichail
相关产品推荐
相关产品推荐

