在这里插入图片描述

案例概述

FutureBuilder 是 Flutter 中用于处理单次异步操作的组件。与 StreamBuilder 不同,FutureBuilder 只处理一个 Future 对象,适合处理一次性的异步操作如网络请求、文件读取等。本案例展示了如何使用 FutureBuilder 创建各种异步应用。

核心概念

1. Future 和异步操作

Future 代表一个可能在未来完成的异步操作。Future 可以返回数据或抛出错误。FutureBuilder 通过监听 Future,在操作完成时自动更新 UI。

2. FutureBuilder 状态管理

FutureBuilder 有三个主要状态:等待、完成、错误。通过检查 AsyncSnapshot 可以为不同状态提供不同的 UI。

3. 异步操作的生命周期

Future 一旦创建就开始执行。需要正确处理异步操作的生命周期,避免内存泄漏。

代码详解

示例 1:基础数据加载

class BasicFutureExample extends StatelessWidget {
  Future<String> _loadData() async {
    await Future.delayed(const Duration(seconds: 2));
    return '数据加载完成';
  }

  
  Widget build(BuildContext context) {
    return FutureBuilder<String>(
      future: _loadData(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const CircularProgressIndicator();
        }

        if (snapshot.hasError) {
          return Text('错误: ${snapshot.error}');
        }

        return Text(snapshot.data ?? '无数据');
      },
    );
  }
}

代码解释: 这个示例展示了 FutureBuilder 的基础用法。_loadData() 方法返回一个 Future,模拟异步操作。FutureBuilder 监听这个 Future,在等待时显示加载指示器,完成时显示数据。snapshot.connectionState 用于检查异步操作的状态。

示例 2:列表数据加载

class ListFutureExample extends StatelessWidget {
  Future<List<String>> _loadItems() async {
    await Future.delayed(const Duration(seconds: 2));
    return ['项目1', '项目2', '项目3', '项目4', '项目5'];
  }

  
  Widget build(BuildContext context) {
    return FutureBuilder<List<String>>(
      future: _loadItems(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Center(child: CircularProgressIndicator());
        }

        if (snapshot.hasError) {
          return Center(child: Text('错误: ${snapshot.error}'));
        }

        return ListView.builder(
          itemCount: snapshot.data?.length ?? 0,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(snapshot.data![index]),
            );
          },
        );
      },
    );
  }
}

代码解释: 这个示例展示了如何使用 FutureBuilder 加载列表数据。_loadItems() 返回一个包含字符串列表的 Future。FutureBuilder 在数据加载完成后,使用 ListView.builder 显示列表。这种方式适合从网络或数据库加载列表数据。

示例 3:自定义加载 UI

class CustomLoadingExample extends StatelessWidget {
  Future<Map<String, dynamic>> _loadUserData() async {
    await Future.delayed(const Duration(seconds: 2));
    return {
      'name': '张三',
      'email': 'zhangsan@example.com',
      'age': 28,
    };
  }

  
  Widget build(BuildContext context) {
    return FutureBuilder<Map<String, dynamic>>(
      future: _loadUserData(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const CircularProgressIndicator(),
              const SizedBox(height: 16),
              const Text('加载用户信息中...'),
            ],
          );
        }

        if (snapshot.hasError) {
          return Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Icon(Icons.error, color: Colors.red, size: 48),
              const SizedBox(height: 16),
              Text('加载失败: ${snapshot.error}'),
            ],
          );
        }

        final data = snapshot.data!;
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('姓名: ${data['name']}'),
            Text('邮箱: ${data['email']}'),
            Text('年龄: ${data['age']}'),
          ],
        );
      },
    );
  }
}

代码解释: 这个示例展示了如何为不同的状态提供自定义 UI。加载状态显示进度指示器和文本,错误状态显示错误图标和消息,完成状态显示用户信息。这种方式提供了更好的用户体验。

示例 4:错误处理

class ErrorHandlingExample extends StatelessWidget {
  Future<String> _loadDataWithError() async {
    await Future.delayed(const Duration(seconds: 1));
    throw Exception('网络连接失败');
  }

  
  Widget build(BuildContext context) {
    return FutureBuilder<String>(
      future: _loadDataWithError(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const CircularProgressIndicator();
        }

        if (snapshot.hasError) {
          return Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Icon(Icons.warning, color: Colors.orange, size: 48),
              const SizedBox(height: 16),
              Text('错误: ${snapshot.error}'),
              const SizedBox(height: 16),
              ElevatedButton(
                onPressed: () {
                  // 重试逻辑
                },
                child: const Text('重试'),
              ),
            ],
          );
        }

        return Text(snapshot.data ?? '无数据');
      },
    );
  }
}

代码解释: 这个示例展示了如何处理异步操作中的错误。当 Future 抛出异常时,snapshot.hasError 为 true,snapshot.error 包含错误信息。可以提供重试按钮让用户重新加载数据。

示例 5:多个 Future 组合

class MultipleFuturesExample extends StatelessWidget {
  Future<String> _loadUser() async {
    await Future.delayed(const Duration(seconds: 1));
    return '用户数据';
  }

  Future<String> _loadPosts() async {
    await Future.delayed(const Duration(seconds: 2));
    return '文章数据';
  }

  
  Widget build(BuildContext context) {
    return FutureBuilder<List<String>>(
      future: Future.wait([_loadUser(), _loadPosts()]),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const CircularProgressIndicator();
        }

        if (snapshot.hasError) {
          return Text('错误: ${snapshot.error}');
        }

        return Column(
          children: [
            Text('用户: ${snapshot.data![0]}'),
            Text('文章: ${snapshot.data![1]}'),
          ],
        );
      },
    );
  }
}

代码解释: 这个示例展示了如何使用 Future.wait() 组合多个 Future。Future.wait() 等待所有 Future 完成,然后返回结果列表。这种方式适合需要加载多个数据源的场景。

高级话题

1. 动态/响应式设计

FutureBuilder 可以根据屏幕大小提供不同的 UI 布局。

2. 动画与过渡

可以在数据加载完成时添加过渡动画。

3. 搜索/过滤/排序

加载的数据可以进行搜索、过滤、排序操作。

4. 选择与批量操作

可以在列表中实现项目选择功能。

5. 加载与缓存

可以缓存已加载的数据,避免重复加载。

6. 键盘导航

FutureBuilder 可以与 Focus 组件结合。

7. 无障碍支持

通过 Semantics 提供无障碍支持。

8. 样式自定义

根据加载状态动态改变样式。

9. 数据持久化/导出

加载的数据可以保存到本地存储。

10. 单元测试与集成测试

Future 可以通过单元测试验证。

PC 端适配要点

  • 在高分辨率屏幕上调整 UI 元素大小
  • 处理长时间加载的情况
  • 提供清晰的加载和错误提示

实际应用场景

  • 网络数据加载:API 请求
  • 文件读取:本地文件操作
  • 数据库查询:数据库操作
  • 初始化操作:应用启动时的初始化

扩展建议

  • 学习网络请求库(如 http、dio)
  • 研究缓存策略
  • 探索错误恢复机制
  • 集成数据库操作

总结

FutureBuilder 是处理单次异步操作的强大工具。通过正确使用 FutureBuilder,可以创建响应式的异步应用。理解 Future 的生命周期、状态管理和错误处理是关键。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐