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

Flutter应用:预加载存于Google Sheets的低频次更新主数据的最佳位置?

Flutter 预加载低变更主数据的优化方案

你的当前方案直接在main中调用异步preLoadData,会导致runApp立即执行,UI启动时数据大概率还未加载完成,容易出现空数据、页面异常等问题。针对URL列表这类每日仅需加载一次的低变更数据,推荐以下几个更优方案:

1. 闪屏页+FutureBuilder 等待加载完成

通过闪屏页过渡,直到数据加载完成再进入主页面,给用户明确的加载反馈:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FutureBuilder(
        future: preLoadData(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            // 自定义闪屏页,可添加加载动画
            return const Scaffold(
              body: Center(child: CircularProgressIndicator()),
            );
          } else if (snapshot.hasError) {
            // 加载失败时显示重试页面
            return Scaffold(
              body: Center(
                child: ElevatedButton(
                  onPressed: () => preLoadData(),
                  child: const Text("重试加载"),
                ),
              ),
            );
          } else {
            // 数据就绪,进入主页面
            return const HomePage();
          }
        },
      ),
    );
  }
}

2. 本地缓存+时间校验 实现每日加载

结合SharedPreferences或其他本地存储工具,记录最后加载时间,仅当超过24小时才请求Google Sheets,避免重复网络请求:

Future<void> preLoadData() async {
  final prefs = await SharedPreferences.getInstance();
  final lastLoadTimestamp = prefs.getInt('last_load_time');
  final now = DateTime.now().millisecondsSinceEpoch;
  const oneDayInMs = 86400000; // 24小时的毫秒数

  List<String> urlList;
  if (lastLoadTimestamp == null || now - lastLoadTimestamp > oneDayInMs) {
    // 从Google Sheets拉取最新数据
    urlList = await _fetchFromGoogleSheets();
    // 保存到本地缓存
    await prefs.setStringList('cached_urls', urlList);
    // 更新最后加载时间
    await prefs.setInt('last_load_time', now);
  } else {
    // 直接读取本地缓存数据
    urlList = prefs.getStringList('cached_urls') ?? [];
  }

  // 将数据存入全局可访问的位置(比如全局变量、状态管理工具)
  AppGlobals.urlList = urlList;
}

// 模拟Google Sheets数据请求
Future<List<String>> _fetchFromGoogleSheets() async {
  // 这里替换为实际的Google Sheets API请求逻辑
  await Future.delayed(const Duration(seconds: 2));
  return ["https://example1.com", "https://example2.com"];
}

// 全局变量示例
class AppGlobals {
  static List<String> urlList = [];
}

3. 状态管理工具的异步初始化

用Riverpod、Provider等状态管理工具封装数据加载逻辑,让页面自动监听数据状态变化,无需手动处理异步流程:

以Riverpod为例:

// 定义数据提供者
final urlListProvider = FutureProvider<List<String>>((ref) async {
  final prefs = await SharedPreferences.getInstance();
  final lastLoadTimestamp = prefs.getInt('last_load_time');
  final now = DateTime.now().millisecondsSinceEpoch;
  const oneDayInMs = 86400000;

  if (lastLoadTimestamp == null || now - lastLoadTimestamp > oneDayInMs) {
    final urlList = await _fetchFromGoogleSheets();
    await prefs.setStringList('cached_urls', urlList);
    await prefs.setInt('last_load_time', now);
    return urlList;
  } else {
    return prefs.getStringList('cached_urls') ?? [];
  }
});

// 主页面使用数据
class HomePage extends ConsumerWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final urlListAsync = ref.watch(urlListProvider);
    
    return urlListAsync.when(
      loading: () => const Center(child: CircularProgressIndicator()),
      error: (err, stack) => Center(
        child: ElevatedButton(
          onPressed: () => ref.invalidate(urlListProvider),
          child: const Text("重试加载"),
        ),
      ),
      data: (urlList) {
        return ListView.builder(
          itemCount: urlList.length,
          itemBuilder: (ctx, index) => ListTile(title: Text(urlList[index])),
        );
      },
    );
  }
}

方案对比

  • 闪屏页方案:适合需要确保数据完全加载后再进入主流程的场景,用户体验流畅
  • 缓存+时间校验:核心是减少不必要的网络请求,降低服务器压力,同时保证数据每日更新
  • 状态管理方案:代码解耦性更强,适合复杂应用,页面可自动响应数据变化

内容的提问来源于stack exchange,提问作者jigar1859

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 15:55:01