Почему мой провайдер AsyncValue в Riverpod бесконечно возвращался в состояние загрузки?

В настоящее время я изучаю Riverpod и пытаюсь внедрить Riverpod в свой BottomSheetModal. Который будет запущен на основе сканера QRcode. Затем после сканирования я хочу, чтобы он извлек данные из Firestore и представил их пользователю внутри модального окна.

часть 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");
                }
              });
        });

Однако объект My AsyncValue.when продолжает возвращаться в виде бесконечного состояния загрузки вместо возврата данных. Я почти уверен, что делаю что-то не так в отношении части кода провайдера, но после нескольких часов поиска в Google и отладки. Я не мог определить причину, по которой он не загружается. Так что я мог бы использовать некоторые свежие глаза здесь.

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;
  }
}

Я знал, что в этом случае виджет FutureBuilder отлично сработает. но я действительно хочу понять Riverpod и поэтому пытался использовать его как можно больше. Кроме того, он кажется более читабельным для меня. И поэтому я оценил объяснение того, что я сделал неправильно и как это исправить. Спасибо!

(Не уверен, что это связано, поскольку, согласно многим потокам, они нужны только для поддержки основных файлов. Но на всякий случай вот сгенерированный код из build_runner)

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'scanned_shipment_out_provider.dart';

// **************************************************************************
// RiverpodGenerator
// **************************************************************************

String _$getShipmentOutDataHash() =>
    r'63e7aae52cf51686a22aad856f1c414e4ec35a2f';

/// Copied from Dart SDK
class _SystemHash {
  _SystemHash._();

  static int combine(int hash, int value) {
    // ignore: parameter_assignments
    hash = 0x1fffffff & (hash + value);
    // ignore: parameter_assignments
    hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
    return hash ^ (hash >> 6);
  }

  static int finish(int hash) {
    // ignore: parameter_assignments
    hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
    // ignore: parameter_assignments
    hash = hash ^ (hash >> 11);
    return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
  }
}

typedef GetShipmentOutDataRef
    = AutoDisposeFutureProviderRef<FirestoreShipmentOutData?>;

/// See also [getShipmentOutData].
@ProviderFor(getShipmentOutData)
const getShipmentOutDataProvider = GetShipmentOutDataFamily();

/// See also [getShipmentOutData].
class GetShipmentOutDataFamily
    extends Family<AsyncValue<FirestoreShipmentOutData?>> {
  /// See also [getShipmentOutData].
  const GetShipmentOutDataFamily();

  /// See also [getShipmentOutData].
  GetShipmentOutDataProvider call({
    required String shipmentTrack,
    required DateTime dateNow,
  }) {
    return GetShipmentOutDataProvider(
      shipmentTrack: shipmentTrack,
      dateNow: dateNow,
    );
  }

  @override
  GetShipmentOutDataProvider getProviderOverride(
    covariant GetShipmentOutDataProvider provider,
  ) {
    return call(
      shipmentTrack: provider.shipmentTrack,
      dateNow: provider.dateNow,
    );
  }

  static const Iterable<ProviderOrFamily>? _dependencies = null;

  @override
  Iterable<ProviderOrFamily>? get dependencies => _dependencies;

  static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;

  @override
  Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
      _allTransitiveDependencies;

  @override
  String? get name => r'getShipmentOutDataProvider';
}

/// See also [getShipmentOutData].
class GetShipmentOutDataProvider
    extends AutoDisposeFutureProvider<FirestoreShipmentOutData?> {
  /// See also [getShipmentOutData].
  GetShipmentOutDataProvider({
    required this.shipmentTrack,
    required this.dateNow,
  }) : super.internal(
          (ref) => getShipmentOutData(
            ref,
            shipmentTrack: shipmentTrack,
            dateNow: dateNow,
          ),
          from: getShipmentOutDataProvider,
          name: r'getShipmentOutDataProvider',
          debugGetCreateSourceHash:
              const bool.fromEnvironment('dart.vm.product')
                  ? null
                  : _$getShipmentOutDataHash,
          dependencies: GetShipmentOutDataFamily._dependencies,
          allTransitiveDependencies:
              GetShipmentOutDataFamily._allTransitiveDependencies,
        );

  final String shipmentTrack;
  final DateTime dateNow;

  @override
  bool operator ==(Object other) {
    return other is GetShipmentOutDataProvider &&
        other.shipmentTrack == shipmentTrack &&
        other.dateNow == dateNow;
  }

  @override
  int get hashCode {
    var hash = _SystemHash.combine(0, runtimeType.hashCode);
    hash = _SystemHash.combine(hash, shipmentTrack.hashCode);
    hash = _SystemHash.combine(hash, dateNow.hashCode);

    return _SystemHash.finish(hash);
  }
}
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не совсем эксперт по Riverpod, но я бы сказал, что всякий раз, когда вы

var shipmentoutdataref = ref.watch(getShipmentOutDataProvider(
                    shipmentTrack: barcode.barcodes.first.rawValue!,
                    dateNow: dateNow,
                  ));

получает данные, снова вызывается построитель для построения загруженных данных. Однако в этом случае ваш shipmentoutdataref изменится в процессе, так как dateNow будет другим, и, таким образом, вы окажетесь с другим поставщиком (т. Этот новый провайдер будет находиться в состоянии загрузки, и как только он получит данные, произойдет та же последовательность. Возможно, вы сможете исправить это, переместив dateNow куда-нибудь внутри провайдеров, а не в «инициализатор», если это возможно.

да, я сделал то, что вы сказали, и переместил переменную dateNow из виджета в мой провайдер, и это устранило проблемы. Большое спасибо! Так что в моем понимании. в основном DateTime.now() будет постоянно перезапускаться, что заставит ref.watch продолжать запускать состояние загрузки без остановок? Я правильно понимаю задачу?

Jirayuth Porka 21.05.2023 16:18

Вы еще не совсем там. Ваш getShipmentOutDataProvider является семейным поставщиком (riverpod.dev/docs/concepts/modifiers/family). Это означает, что это провайдер, который может принимать дополнительные аргументы (в вашем старом коде: shippingTrack и dateNow). Идея этих провайдеров заключается в том, что их возвращаемое значение может отличаться в зависимости от этих аргументов, но остается тем же самым, если аргументы остаются прежними. Если вы вызовете провайдера с теми же аргументами, он запомнит, что вы вызывали его раньше, и будет использовать те же данные, но с другими аргументами, это будет совершенно другой провайдер.

Wessel 22.05.2023 07:31

В вашем FutureBuilder каждый раз, когда вызывается строитель, dateNow будет создаваться снова (поэтому не каждый раз, когда изменяется время, а каждый раз, когда виджет создается снова), и поэтому аргументы вашего familyprovider меняются. Поэтому будет создан провайдер, отличный от провайдера из более ранней сборки, и, таким образом, он все еще будет находиться в состоянии загрузки. При перемещении dateNow внутри провайдера аргументы не меняются при каждой сборке виджета, поэтому он «запомнит» провайдера из более раннего и будет использовать его готовое состояние.

Wessel 22.05.2023 07:34

Другие вопросы по теме