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

Flutter:如何从其他组件重新构建FutureBuilder组件?

How to Refresh Your Weather Widget with FutureBuilder

Got it, let's fix this refresh issue. The core problem here is that your FutureBuilder is using a static future that only runs once when the widget initializes. To get it to reload, we need to update that future and trigger a rebuild when the button is pressed. Here's a clean, maintainable approach:


Step 1: Lift State to the Parent Widget

We'll move the weather future and cooldown logic up to your main parent widget (like MyHomePage). This way both the weather widget and the refresh button can access and modify the state.

Main.dart:

import 'package:flutter/material.dart';
import 'current_weather_widget.dart';
import 'some_other_widget.dart';

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late Future<CurrentWeatherFactory> _weatherFuture;
  DateTime? _lastRefreshTime;
  final int _cooldownSeconds = 10; // Adjust this to your desired cooldown

  @override
  void initState() {
    super.initState();
    // Initialize with the first API call
    _weatherFuture = _fetchWeatherData();
  }

  // Your existing API call logic
  Future<CurrentWeatherFactory> _fetchWeatherData() {
    return CurrentWeatherFactory.fetchData(); // Replace with your actual API method
  }

  void _attemptRefresh() {
    final now = DateTime.now();
    // Check if cooldown has passed
    if (_lastRefreshTime == null || 
        now.difference(_lastRefreshTime!).inSeconds >= _cooldownSeconds) {
      setState(() {
        // Update the future to trigger a new API call
        _weatherFuture = _fetchWeatherData();
        _lastRefreshTime = now;
      });
    } else {
      final remaining = _cooldownSeconds - now.difference(_lastRefreshTime!).inSeconds;
      print("Wait $remaining seconds before refreshing again");
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          // Pass the future to your weather widget
          CurrentWeatherWidget(weatherFuture: _weatherFuture),
          // Pass the refresh callback to your button widget
          SomeOtherWidget(onRefreshPressed: _attemptRefresh),
        ],
      ),
    );
  }
}

Step 2: Update CurrentWeatherWidget to Accept the Future

Make your weather widget stateless (since it no longer holds its own state) and accept the future as a parameter:

current_weather_widget.dart:

import 'package:flutter/material.dart';

class CurrentWeatherWidget extends StatelessWidget {
  final Future<CurrentWeatherFactory> weatherFuture;

  const CurrentWeatherWidget({Key? key, required this.weatherFuture}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        FutureBuilder<CurrentWeatherFactory>(
          future: weatherFuture,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              // Your existing weather display logic here
              return Text("Current Temp: ${snapshot.data!.temperature}°C");
            } else if (snapshot.hasError) {
              return Text("Error loading weather: ${snapshot.error}");
            }
            // Show loading indicator while fetching
            return CircularProgressIndicator();
          },
        ),
        // Add other weather-related widgets here
      ],
    );
  }
}

Step 3: Update the Button Widget to Use the Callback

Modify your button widget to accept the refresh callback from the parent:

some_other_widget.dart:

import 'package:flutter/material.dart';

class SomeOtherWidget extends StatelessWidget {
  final VoidCallback onRefreshPressed;

  const SomeOtherWidget({Key? key, required this.onRefreshPressed}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      onPressed: onRefreshPressed,
      child: Text('RELOAD NEW DATA'),
    );
  }
}

How This Works:

  1. When the button is pressed, it triggers _attemptRefresh in the parent widget.
  2. The parent checks if the cooldown period has passed. If yes, it creates a new future (which runs your API call again) and calls setState.
  3. setState rebuilds the parent, passing the new future to CurrentWeatherWidget.
  4. The FutureBuilder detects the new future, runs it, and updates the UI with fresh weather data.

This approach follows Flutter's state management best practices by keeping state in a single, accessible place, and avoids messy workarounds like global keys.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:19:30