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

为何我的Riverpod中AsyncValue Provider一直处于加载状态?

问题:Riverpod在BottomSheetModal中持续加载无法返回Firestore数据

我正在学习Riverpod,尝试在二维码扫描触发的BottomSheetModal中使用它。扫描完成后想从Firestore获取数据并在模态框展示,但AsyncValue.when始终处于加载状态,无法返回数据。用FutureBuilder可以正常工作,但希望用Riverpod实现。

相关代码

Scanned_Shipment_Modal.dart 部分代码

showModalBottomSheet(
        context: context,
        backgroundColor: Colors.transparent,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(50)),
        isScrollControlled: true,
        builder: (context) {
          return FutureBuilder(
              future: Future.value(capture),
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  var dateNow = DateTime.now();
                  var shipmentoutdataref = ref.watch(getShipmentOutDataProvider(
                    shipmentTrack: barcode.barcodes.first.rawValue!,
                    dateNow: dateNow,
                  ));
                  return shipmentoutdataref.when(
                      data: (data) {
                        debugPrint(data.toString());
                        return Wrap(
                          children: [
                            ScannedShipmentOutModal(shipmentoutdataref: data)
                          ],
                        );
                      },
                      error: (error, stackTrace) => ErrorPopup().errorPopup(
                          context, "Error", "No Da"),
                      loading: () {
                        return const LoadingCircle(
                          height: 200,
                          width: 200,
                        );
                      });
                } else {
                  return ErrorPopup()
                  .errorPopup(context, "Error", "No Data Avaliable");
                }
              });
        });

scanned_shipment_out_provider.dart 代码

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:intl/intl.dart';
import 'package:logistec/models/Firebase/model/firestore_data_models.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'scanned_shipment_out_provider.g.dart';

@riverpod
Future<FirestoreShipmentOutData?> getShipmentOutData(GetShipmentOutDataRef ref,
    {required String shipmentTrack, required DateTime dateNow}) async {
  FirebaseFirestore firestore = FirebaseFirestore.instance;
  String getformattedDate = DateFormat("dd-MM-yy").format(dateNow);
  var dataref =
      firestore.collection("DHL_Service_RecheckData").doc(getformattedDate);
  var data = await dataref.get();
  try {
    var dataList = data.get(shipmentTrack);
    return FirestoreShipmentOutData.fromJSON(dataList);
  } catch (e) {
    return null;
  }
}

问题原因分析

  1. AutoDispose Provider 被提前销毁:生成代码显示这是AutoDisposeFutureProvider,BottomSheet的builder会多次重建,每次重建时DateTime.now()生成新时间对象,导致Provider参数变化、创建新实例,旧实例被销毁,新实例重新请求数据,陷入循环加载。
  2. FutureBuilder与Riverpod混用冲突:在FutureBuilder的builder中调用ref.watch,builder重建时会重复执行ref.watch,结合AutoDispose特性,导致Provider无法稳定完成请求。
  3. 异常处理隐藏问题:Provider中try-catch直接返回null,Riverpod会将null视为正常数据;若Firestore请求或数据解析出现隐藏异常,会导致状态无法正确更新,表现为持续加载。

修正方案

方案1:稳定Provider参数并调整AutoDispose特性

步骤1:固定dateNow参数

扫描完成后立即获取固定时间,避免在builder中重复生成:

// 扫描完成后固定时间
final fixedDate = DateTime.now();
showModalBottomSheet(
  context: context,
  // 其他参数不变
  builder: (context) {
    return Consumer(builder: (context, ref, _) {
      var shipmentoutdataref = ref.watch(getShipmentOutDataProvider(
        shipmentTrack: barcode.barcodes.first.rawValue!,
        dateNow: fixedDate,
      ));
      return shipmentoutdataref.when(
        data: (data) {
          if (data == null) {
            return ErrorPopup().errorPopup(context, "Error", "No Data Available");
          }
          debugPrint(data.toString());
          return Wrap(
            children: [ScannedShipmentOutModal(shipmentoutdataref: data)],
          );
        },
        error: (error, stackTrace) => ErrorPopup().errorPopup(
          context, "Error", error.toString()),
        loading: () => const LoadingCircle(height: 200, width: 200),
      );
    });
  },
);

步骤2:设置Provider保持存活(可选)

如果不需要自动销毁Provider,添加keepAlive: true并重新运行build_runner:

@riverpod(keepAlive: true)
Future<FirestoreShipmentOutData?> getShipmentOutData(...) async {
  // 原有代码不变
}

方案2:优化Provider异常处理

捕获异常时抛出错误,让Riverpod的when方法进入error分支,便于排查问题:

@riverpod
Future<FirestoreShipmentOutData?> getShipmentOutData(GetShipmentOutDataRef ref,
    {required String shipmentTrack, required DateTime dateNow}) async {
  FirebaseFirestore firestore = FirebaseFirestore.instance;
  String getformattedDate = DateFormat("dd-MM-yy").format(dateNow);
  var dataref = firestore.collection("DHL_Service_RecheckData").doc(getformattedDate);
  var data = await dataref.get();
  
  if (!data.exists) {
    throw Exception("Document not found for date: $getformattedDate");
  }
  
  try {
    var dataList = data.get(shipmentTrack);
    return FirestoreShipmentOutData.fromJSON(dataList);
  } catch (e) {
    throw Exception("Shipment track $shipmentTrack not found: ${e.toString()}");
  }
}

方案3:移除FutureBuilder,直接使用Consumer

已有扫描完成的capture数据,无需用FutureBuilder包裹,直接在BottomSheet中用Consumer监听Provider:

showModalBottomSheet(
  context: context,
  backgroundColor: Colors.transparent,
  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(50)),
  isScrollControlled: true,
  builder: (context) {
    final fixedDate = DateTime.now();
    return Consumer(builder: (context, ref, _) {
      var shipmentoutdataref = ref.watch(getShipmentOutDataProvider(
        shipmentTrack: barcode.barcodes.first.rawValue!,
        dateNow: fixedDate,
      ));
      return shipmentoutdataref.when(
        data: (data) {
          return data != null 
              ? Wrap(children: [ScannedShipmentOutModal(shipmentoutdataref: data)])
              : ErrorPopup().errorPopup(context, "Error", "No Data Available");
        },
        error: (error, stackTrace) => ErrorPopup().errorPopup(context, "Error", error.toString()),
        loading: () => const LoadingCircle(height: 200, width: 200),
      );
    });
  },
);

内容的提问来源于stack exchange,提问作者Jirayuth Porka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 21:27:20