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

如何在Flutter的initState中使用Provider实现条件性数据请求

问题解决方案:按需触发产品数据拉取逻辑

问题分析

当前代码的核心问题在于:仅在页面初始化时调用一次数据拉取,没有监听IsProductChangedProvider的状态变化,也未在拉取完成后更新状态值,导致无法实现"仅当isTheProductChanged为true时拉取数据,拉取后设为false"的逻辑。

修改步骤

1. 优化Provider状态管理

为IsProductChangedProvider新增明确的状态设置方法,避免使用toggle操作带来的歧义:

// is_products_changed_provider.dart
import 'package:flutter/material.dart';

class IsProductChangedProvider extends ChangeNotifier {
  bool isTheProductChanged = true;

  // 保留原有状态切换功能(若需)
  void toggleChangedStatus() {
    isTheProductChanged = !isTheProductChanged;
    notifyListeners();
  }

  // 明确设置状态为false,用于拉取完成后更新
  void setChangedStatusFalse() {
    isTheProductChanged = false;
    notifyListeners();
  }
}

2. 调整Products页面逻辑

修改页面代码,实现状态监听、按需拉取及状态重置:

// products.dart
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:wineasy/components/error_card.dart';
import 'package:wineasy/components/side_nav_bar.dart';
import 'package:wineasy/components/single_product_card.dart';
import 'package:wineasy/models/product_model.dart';
import './is_products_changed_provider.dart'; // 确保路径正确

class Products extends StatefulWidget {
  const Products({Key? key}) : super(key: key);

  @override
  State<Products> createState() => _ProductsState();
}

class _ProductsState extends State<Products> {
  Future<List<ProductModel>>? _futureProducts;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      drawer: const SideNavBar(),
      appBar: AppBar(
        backgroundColor: Colors.transparent,
      ),
      body: Consumer<IsProductChangedProvider>(
        builder: (context, provider, child) {
          // 当状态为true且无正在进行的请求时,触发数据拉取
          if (provider.isTheProductChanged && _futureProducts == null) {
            _futureProducts = fetchProductData().whenComplete(() {
              // 拉取完成后重置状态
              provider.setChangedStatusFalse();
              // 清空请求实例,以便下次状态变化时重新触发
              setState(() {
                _futureProducts = null;
              });
            });
          }

          // 初始化时无数据,主动触发一次拉取(可选,根据业务需求调整)
          if (!provider.isTheProductChanged && _futureProducts == null) {
            _futureProducts = fetchProductData();
          }

          return FutureBuilder(
            future: _futureProducts,
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return const Center(
                  child: Padding(
                    padding: EdgeInsets.symmetric(horizontal: 30.0),
                    child: LinearProgressIndicator(),
                  ),
                );
              } else if (snapshot.hasError) {
                return const Center(
                  child: ErrorCard(errorText: "Failed to load data"),
                );
              } else if (snapshot.hasData) {
                List<ProductModel> productsList = snapshot.data as List<ProductModel>;

                return Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 15.0),
                  child: GridView.builder(
                    gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
                      maxCrossAxisExtent: 320,
                      crossAxisSpacing: 15.0,
                      mainAxisSpacing: 15.0,
                      mainAxisExtent: 308
                    ),
                    itemCount: productsList.length,
                    itemBuilder: (context, index) {
                      return SingleProductCard(
                        productName: productsList[index].productName,
                        productPrice: productsList[index].price,
                        productType: productsList[index].typeOfProduct,
                        productCategory: productsList[index].categoryOfProduct,
                        productDescription: productsList[index].description,
                        imageFile: productsList[index].imageFile,
                        productId: productsList[index].productId,
                        isAvailable: productsList[index].isAvailable,
                      );
                    },
                  ),
                );
              } else {
                return const Center(child: CircularProgressIndicator());
              }
            },
          );
        },
      ),
    );
  }

  Future<List<ProductModel>> fetchProductData() async {
    const String getProductsUrl = "http://localhost:4848/api/product-list";

    try {
      Response serverResponse = await Dio().get(getProductsUrl);

      List<ProductModel> productsList = (serverResponse.data as List<dynamic>)
          .map((productData) => ProductModel.fromJson(productData))
          .toList();

      return productsList;
    } catch (e) {
      print('Error fetching data: $e');
      rethrow;
    }
  }
}

核心修改说明

  • 新增setChangedStatusFalse方法:明确控制状态为false,避免toggle操作的不确定性
  • 新增_futureProducts变量:管理当前请求状态,防止重复触发接口调用
  • 状态监听逻辑:在Consumer中实时监听isTheProductChanged,满足条件时自动触发拉取
  • 请求完成处理:拉取结束后立即重置状态,并清空请求实例,确保下次状态变化时能重新触发

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 23:26:01