Reputation: 427
I have a FutureProvider with Family parameters as below:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class I_Rem_Params {
final String adminID;
final String companyID;
final int month;
I_Rem_Params(
{required this.adminID, required this.companyID, required this.month});
}
final iRemReportsFamily =
FutureProvider.family<double, I_Rem_Params>((ref, iremparams) async {
final db = FirebaseFirestore.instance;
final admins = db.collection("Admins");
final admin = admins.doc(iremparams.adminID);
final companies = admin.collection("Companies");
final company = companies.doc(iremparams.companyID);
final imports = company.collection("Imports");
final getImports = await imports.get();
final val = getImports.docs.length.toDouble();
print("value at provider : " + val.toString());
return val;
});
I am printing the value before sent by FutureProvider as below:
value at provider : 2
I am getting and printing the AsyncValue at widget side as below:
AsyncValue<double> juneTotalValue = ref.watch(iRemReportsFamily(
I_Rem_Params(
adminID: adminID!, companyID: widget.companyID, month: 5)));
print("value at widget : " + juneTotalValue.value.toString());
print("runtimetype at widget : " + juneTotalValue.runtimeType.toString());
AsyncValue printed as below on widget side:
value at widget : null
runtimetype at widget : AsyncLoading<double>
And injecting the AsyncValue as follows:
....... children: [
juneTotalValue.when(
data: (data) => Text(data.toString()),
error: (error, stack) => Text(error.toString()),
loading: () => const CircularProgressIndicator()),
const SizedBox(
height: 38,
),........
Handling of AsyncValue not display value of 2 sent by FutureProvider but only display loading widget of CircularProgressIndicator().
QUESTION: Why AsyncValue is Null despite there is a number sent by FutureProvider ?
Upvotes: 0
Views: 761
Reputation: 17576
This mainly has to do with how you are creating your FutureProvider.family.
Since the .family modifier creates a new provider for each unique value that is passed to it, you need to confirm that the hashcode of the input value is the same each time you call the provider. If it's not, a new provider will be created each time. If you're using ref.watch, you can get caught in a loop:
This is also pointed out in the Parameter restrictions section of the Riverpod docs. In general, you should create your .family providers using a primitive data type (like int, bool, double, or string).
If you need to use something else, then you'll need to override the hashcode method of your object using a package like equatable.
class Person {
const Person(this.name);
final String name;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Person &&
runtimeType == other.runtimeType &&
name == other.name;
@override
int get hashCode => name.hashCode;
}
Upvotes: 1