【开源鸿蒙跨平台开发训练营】Flutter框架鸿蒙应用的缓存优化提升加载性能实战
本文档介绍了App首页数据缓存的实现方案,通过SharedPreferences持久化存储作品列表数据,优化用户启动体验。主要实现内容包括:1)新增HomeCacheService管理缓存的读写清除;2)首页启动流程改为先读缓存再静默刷新;3)网络请求成功后更新缓存。该方案解决了首屏空白等待问题,同时保证数据时效性,设置页支持一键清除缓存。关键点包括缓存服务设计、静默刷新逻辑和异常处理,适用于中小
·
发现目前项目每次启动都要等待数据加载过程,如果遇到网络不佳时,等待的体验很不好,于是想到增加通过增加缓存来优化下体验。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
文章目录
功能实现说明:首页数据缓存
本文档说明 App 首页数据缓存的实现:启动时优先展示上次缓存的列表数据,避免首屏空白,再在后台静默拉取最新数据并更新缓存。

一、目标与方案
- 目标:
- 启动 App 时,若存在上次成功加载的首页数据,先展示缓存内容,避免「无内容」的空白等待。
- 在展示缓存的同时或之后,后台拉取最新数据;拉取成功后更新列表并写入缓存,供下次启动使用。
- 设置页「清除缓存」同时清除首页数据缓存与图片内存缓存。
- 方案:
- 新增 首页数据缓存服务(
HomeCacheService),使用SharedPreferences持久化作品列表(List<WorkModel>的 JSON)。 - 首页(
HomePage)启动流程改为:先异步读取缓存 → 若有缓存则填充_works/_images/_displayImages并关闭 loading → 再调用原有_loadData(silentIfHasCache: true)做静默刷新;无缓存时仍为「先 loading 再拉取」。 - 网络请求成功后,将本次解析得到的
_works写入HomeCacheService。 - 设置页「清除缓存」中增加调用
HomeCacheService().clear()。
- 新增 首页数据缓存服务(
二、涉及文件
| 文件 | 说明 |
|---|---|
lib/services/home_cache_service.dart |
新增。首页数据缓存服务:读/写/清除作品列表缓存。 |
lib/pages/home_page.dart |
启动时先读缓存再拉取;_loadData 支持静默刷新并写入缓存。 |
lib/pages/profile_page.dart |
「清除缓存」时同时清除首页数据缓存。 |
无新增 pub 依赖,沿用现有 shared_preferences。
三、流程说明
3.1 首次启动(无缓存)
initState→_initWithCacheThenLoad()。_homeCache.getCachedWorks()返回null。- 直接执行
_loadData(silentIfHasCache: false),全屏 loading,请求网络 → 解析 → 填充列表并 保存到缓存 → 关闭 loading。
3.2 再次启动(有缓存)
initState→_initWithCacheThenLoad()。_homeCache.getCachedWorks()返回上次的作品列表。- 用缓存填充
_works、_images,执行_loadMore()得到首屏_displayImages,setState将_isLoading = false,立即展示缓存内容。 - 执行
_loadData(silentIfHasCache: true):不置_isLoading = true,在后台请求网络;成功则更新列表并再次写入缓存;失败仅保留当前缓存展示,不弹错误(用户可下拉刷新重试)。
3.3 下拉刷新 / 重试
- 与原先一致:
_refreshData()清空展示并置_isLoading = true,调用_loadData()(不传silentIfHasCache,即按「无缓存」流程),成功后同样会写入缓存。
四、实现要点
4.1 HomeCacheService
- 存储键:
calm_harbor_home_works_cache。 - 读:
getCachedWorks()→ 从SharedPreferences取 JSON 字符串,解析为List<WorkModel>;异常或空则返回null。 - 写:
saveWorks(List<WorkModel> works)→ 将works.map((w) => w.toJson()).toList()做json.encode后写入;空列表不写。 - 清:
clear()→ 移除该键,供设置页「清除缓存」使用。
单例,与 SettingsService 一样通过 SharedPreferences.getInstance() 获取实例。
4.2 HomePage 与缓存联动
_initWithCacheThenLoad()(在initState中调用):await _homeCache.getCachedWorks()。- 若缓存非空:从作品列表推导
_images(各作品images拼接),赋值_works、_images,清空_displayImages、重置分页,_isLoading = false,再await _loadMore()得到首屏数据。 - 最后统一
await _loadData(silentIfHasCache: cached != null && cached.isNotEmpty)。
_loadData({bool silentIfHasCache = false}):- 若
silentIfHasCache == true且当前_works.isNotEmpty,则不执行setState({ _isLoading = true }),实现静默刷新。 - 网络成功、解析并赋值
_works/_images后,调用await _homeCache.saveWorks(_works),再setState({ _isLoading = false })。
- 若
4.3 设置页清除缓存
_clearCache()中在原有CacheService().clearImageCache()之后增加await HomeCacheService().clear(),一并清除首页数据缓存;提示文案仍使用原有「已清除缓存」/「清除缓存失败」。
五、关键代码
5.1 HomeCacheService 读写
Future<List<WorkModel>?> getCachedWorks() async {
try {
final prefs = await _store;
final jsonStr = prefs.getString(_keyWorks);
if (jsonStr == null || jsonStr.isEmpty) return null;
final list = json.decode(jsonStr) as List<dynamic>?;
if (list == null || list.isEmpty) return null;
return list
.map((e) => WorkModel.fromJson(Map<String, dynamic>.from(e as Map)))
.toList();
} catch (_) {
return null;
}
}
Future<void> saveWorks(List<WorkModel> works) async {
if (works.isEmpty) return;
try {
final prefs = await _store;
final list = works.map((w) => w.toJson()).toList();
await prefs.setString(_keyWorks, json.encode(list));
} catch (_) {}
}
5.2 首页先展示缓存再拉取
Future<void> _initWithCacheThenLoad() async {
final cached = await _homeCache.getCachedWorks();
if (!mounted) return;
if (cached != null && cached.isNotEmpty) {
final allImages = cached.fold<List<String>>([], (acc, w) => acc..addAll(w.images));
if (allImages.isNotEmpty) {
setState(() {
_works = cached;
_images = allImages;
_displayImages.clear();
_currentPage = 0;
_hasMore = _images.isNotEmpty;
_isLoading = false;
});
await _loadMore();
}
}
await _loadData(silentIfHasCache: cached != null && cached.isNotEmpty);
}
5.3 静默刷新与写缓存
Future<void> _loadData({bool silentIfHasCache = false}) async {
final hasCache = silentIfHasCache && _works.isNotEmpty;
if (!hasCache) {
setState(() { _isLoading = true; _errorMessage = null; });
}
try {
// ... 网络请求、解析、赋值 _works / _images / _displayImages / _loadMore() ...
await _homeCache.saveWorks(_works);
if (!mounted) return;
setState(() { _isLoading = false; });
} catch (...) { ... }
}
六、注意事项
- 缓存大小:
SharedPreferences单键有大小限制(部分平台约 2MB),若作品数量或单条数据很大,可考虑改为文件缓存(如应用文档目录下的 JSON 文件)。 - 数据一致性:缓存仅作「上次成功拉取的结果」快照,不保证与服务器实时一致;静默刷新失败时界面仍显示缓存,用户可通过下拉刷新重试。
- 清除缓存:设置页「清除缓存」会同时清除图片内存缓存与首页数据缓存,下次启动将重新走「无缓存」流程,首屏会先出现 loading 再展示数据。

七、小结
通过 HomeCacheService 持久化首页作品列表,并在 HomePage 启动时「先读缓存再静默拉取」,实现了「启动即显示上次内容、后台更新」的体验;设置页清除缓存时一并清理首页数据缓存,与现有图片缓存逻辑统一。
结束语
感谢阅读本帖,如对贴中内容有意见和建议的,欢迎与我联系交流,也欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
更多推荐



所有评论(0)