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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 16:25:32