Flutter从API取数据存LocalStorage实现离线:现有代码缺失什么?
我帮你梳理下当前代码里实现离线功能的几个关键缺失点,以及对应的修复思路:
1. 离线场景下缺少从LocalStorage读取数据的核心逻辑
当前fetchPostsList方法在请求失败时直接抛出异常,完全没考虑离线时读取本地缓存的情况。而且你注释掉的读取代码也没做类型转换——LocalStorage存的是JSON字符串,必须转成PostsList对象才能正常返回使用。
修复后的示例代码:
Future<PostsList> fetchPostsList(String language) async { // 优先从本地缓存读取数据 final cachedData = await storagee.getItem(language); if (cachedData != null) { return PostsList.fromJson(json.decode(cachedData)); } // 本地无缓存时再发起网络请求 try { final response = await http.get(Uri.parse('https://sas-survey.urbanway.net/api/questions/1/${language}')); if (response.statusCode == 200) { final jsonData = json.decode(response.body); // 将网络数据存入本地缓存 await storagee.setItem(language, json.encode(jsonData)); return PostsList.fromJson(jsonData); } else { throw Exception('Failed to load posts from network'); } } catch (e) { // 只有网络失败且无缓存时才抛出异常 throw Exception('Network error and no local cache available: $e'); } }
2. LocalStorage未完成初始化就直接使用
LocalStorage实例需要先调用ready()方法确保初始化完成,否则很容易出现读写失败的情况。你当前的代码直接使用storagee,完全没处理初始化步骤。
修复方式:在组件初始化阶段完成存储准备:
@override void initState() { super.initState(); _prepareStorageAndFetchData(); } Future<void> _prepareStorageAndFetchData() async { // 等待LocalStorage初始化完成 await storagee.ready(); // 初始化后再触发数据获取 setState(() { _fetchFuture = fetchPostsList('en'); }); }
3. FutureBuilder存在重复请求和重复添加数据的问题
每次组件build时,FutureBuilder都会重新执行fetchPostsList(en),导致重复发起网络请求;同时每次都会调用_addItemEn把数据重复添加到resultsListEn里,造成数据冗余。
修复方案:
- 将请求Future缓存到State变量中,避免重复发起请求:
Future<PostsList>? _fetchFuture; // 然后在FutureBuilder里使用这个缓存的Future FutureBuilder<PostsList>( future: _fetchFuture, builder: (context, snapshot) { if(snapshot.hasData){ // 若需维护本地列表,先清空再添加避免重复 resultsListEn.posts.clear(); resultsListEn.posts.addAll(snapshot.data!.posts); return Center(); }else if(snapshot.hasError){ return Text("${snapshot.error}"); } return CircularProgressIndicator(); }, )
4. 缓存键值的一致性问题
当前存储用的键是'en',但你注释的代码里用的是'resultPost',多语言场景下会出现缓存覆盖或读取错误的问题。应该统一用语言标识作为缓存键,比如'en'、'zh'等,确保不同语言的缓存互相独立。
5. _addItemEn和_saveToStorageEn逻辑冗余
既然已经可以在fetchPostsList里直接存储完整的网络响应JSON,拆分单个Post再重新组装存储的逻辑就完全多余了——不仅重复劳动,还可能引入数据不一致的风险。直接存储完整的PostsList JSON更高效可靠。
内容的提问来源于stack exchange,提问作者sh.sejdiu
相关产品推荐
相关产品推荐

