You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 03:59:16