Flutter热重载与热重启结果不同?FutureBuilder重复调用API问题
问题:FutureBuilder调用API时热重启输出两次的原因及解决办法
我尝试在Flutter代码中用FutureBuilder实现API调用,在build函数里调用getData方法,但热重启时打印语句输出两次,热重载时只输出一次,请问问题出在哪里?
代码示例
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; class Practice extends StatefulWidget { const Practice({super.key}); @override State<Practice> createState() => _PracticeState(); } class _PracticeState extends State<Practice> { Future<Map<String,dynamic>> getData() async { final url = "https://dummyjson.com/products"; var res = await http.get(Uri.parse(url)); var body = res.body; print(body.runtimeType); var data = jsonDecode(body); print(data.runtimeType); return data; } @override Widget build(BuildContext context) { return Scaffold( body: FutureBuilder( future: getData(), builder: ( context, snapshot){ return const Scaffold(); } ), ); } }
输出结果
热重启输出
flutter: String flutter: _Map<String, dynamic> flutter: String flutter: _Map<String, dynamic>
热重载输出
flutter: String flutter: _Map<String, dynamic>
问题原因
你直接在FutureBuilder的future参数中调用getData(),而Flutter的build方法会被框架多次触发(比如热重启时组件树重建、debug模式下的双重重建检查、状态变更等场景),每次build执行都会重新调用getData(),导致API请求和打印语句被执行两次。
热重启时应用会完全重新初始化,build方法会被调用两次;而热重载仅刷新代码逻辑,不会完全重建组件树,所以build只执行一次,对应输出也只出现一次。
解决办法
将Future对象提前初始化,避免在build方法中创建:
- 在State类中定义一个
Future成员变量 - 在
initState生命周期方法中初始化这个Future,确保API请求只执行一次
修改后的代码:
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; class Practice extends StatefulWidget { const Practice({super.key}); @override State<Practice> createState() => _PracticeState(); } class _PracticeState extends State<Practice> { late Future<Map<String,dynamic>> _dataFuture; @override void initState() { super.initState(); // 仅在组件初始化时执行一次API请求 _dataFuture = getData(); } Future<Map<String,dynamic>> getData() async { final url = "https://dummyjson.com/products"; var res = await http.get(Uri.parse(url)); var body = res.body; print(body.runtimeType); var data = jsonDecode(body); print(data.runtimeType); return data; } @override Widget build(BuildContext context) { return Scaffold( body: FutureBuilder( future: _dataFuture, // 使用提前初始化的Future对象 builder: ( context, snapshot){ return const Scaffold(); } ), ); } }
这样修改后,无论build方法被调用多少次,getData()只会在组件初始化时执行一次,热重启时也不会重复触发API请求和打印输出。
内容的提问来源于stack exchange,提问作者Pulkit Singhal
相关产品推荐
相关产品推荐

