here is my Future builder its returning an error i think its because of riverpod but i cant find a solution. the error is at the bottom
i tried changedDependencies and didnt work im receiving the list normally and its showing in the console but its not showing in initState.
my objective is to have self loading list whenever the page starts yet everything is fine concerning the data handling the list is being received and the api is connecting its just the snapshot.data
is turning out null for some reason.
its my first time using this type of builder so im hoping im clear enough on the matter.
import 'dart:convert';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import '../models/account.dart';
import '../provider/company_provider.dart';
import '../provider/user_provider.dart';
class AccountFinder extends ConsumerStatefulWidget {
const AccountFinder({super.key});
@override
ConsumerState<AccountFinder> createState() => _AccountFinderState();
}
class _AccountFinderState extends ConsumerState<AccountFinder> {
late Future<List<Account>> accounts;
String searchString = "";
Future<List<Account>> fetchAccounts() async {
var userID = ref.watch(userStateProvider).id;
var companyID = ref.watch(companyStateProvider).comID;
print(userID);
final url = Uri.parse(
'http://api_adress/GetAllActs?CID=$companyID',
);
final headers = {'Content-Type': 'application/json'};
final response = await http.post(
url,
headers: headers,
body: json.encode({
"id": userID,
"userName": "string",
"password": "string",
"loggedIn": true,
"userActive": true,
"userDeleteable": true
}),
);
if (response.statusCode == 200) {
List<dynamic> listAccountsJson = jsonDecode(response.body);
return listAccountsJson
.map((account) => Account.fromJson(account))
.toList();
} else {
throw Exception('Failed to load items');
}
}
@override
void initState() {
super.initState();
accounts = fetchAccounts();
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SafeArea(
child: Container(
height: 40,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Theme.of(context)
.colorScheme
.onBackground
.withOpacity(0.1)),
margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 20),
child: TextField(
onTapOutside: (event) =>
FocusManager.instance.primaryFocus?.unfocus(),
onChanged: (value) {
setState(() {
searchString = value.toLowerCase();
});
},
style: Theme.of(context).textTheme.bodyMedium!,
decoration: InputDecoration(
border: InputBorder.none,
hintText: AppLocalizations.of(context)!.search,
hintStyle: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontSize: 16,
fontWeight: FontWeight.w300,
color: Theme.of(context)
.colorScheme
.onBackground
.withOpacity(0.7)),
prefixIcon: const Icon(
Icons.search,
)),
),
),
),
IconButton(onPressed: fetchAccounts, icon: Icon(Icons.abc)),
const SizedBox(height: 10),
Expanded(
child: FutureBuilder(
builder: (context, AsyncSnapshot<List<Account>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
} else if (!snapshot.hasData) {
return Center(child: Text('No data available'));
} else {
return SingleChildScrollView(
child: ListView.separated(
padding: const EdgeInsets.all(8),
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, int index) {
return snapshot.data![index].actName!
.toLowerCase()
.contains(searchString)
? Card(
elevation: 3,
child: ListTile(
title: Text('${snapshot.data?[index].actName}'),
subtitle: Text(
' ${snapshot.data?[index].actMobileNo}n${snapshot.data?[index].actPhoneNo}n'),
),
)
: Container();
},
separatorBuilder: (BuildContext context, int index) {
return snapshot.data![index].actName!
.toLowerCase()
.contains(searchString)
? const Divider()
: Container();
},
),
);
}
},
future: accounts,
),
),
],
);
}
}
This the error im getting:
dependOnInheritedWidgetOfExactType<UncontrolledProviderScope>() or dependOnInheritedElement() was called before _AccountFinderState.initState() completed.
I/flutter (14799): When an inherited widget changes, for example if the value of Theme.of() changes, its dependent widgets are rebuilt. If the dependent widget's reference to the inherited widget is in a constructor or an initState() method, then the rebuilt dependent widget will not reflect the changes in the inherited widget.
I/flutter (14799): Typically references to inherited widgets should occur in widget build() methods. Alternatively, initialization based on inherited widgets can be placed in the didChangeDependencies method, which is called after initState and whenever the dependencies change thereafter.```
2
Answers
i gave it a Future.delayed(Duration.zero,fetchAccounts()); and its working fine now the real error turned out to be in the widget overlay the constraint werent contraining so the devider had no widtth to be based upon and removed the future builder entirely and left it with ListView.seperated
The error message you’re getting provides a clear hint about the problem:
Inherited widgets, which Riverpod’s providers are built upon, cannot be accessed in
initState()
. This is becauseinitState()
is called before the widget is fully integrated into the widget tree, which means it doesn’t yet have access to the context from the widgets above it.Here’s the solution based on the error:
1. Use
didChangeDependencies
:Instead of fetching the data in
initState()
, override thedidChangeDependencies()
method which is called immediately afterinitState()
and whenever the dependencies (like providers) change:Note: Be cautious when using
didChangeDependencies()
. It can be called multiple times throughout the lifecycle of a widget, especially if the widget depends on multiple InheritedWidgets (e.g., providers, themes, etc.). Thus, you’ll want to make sure you don’t redundantly re-fetch data.2. Remove the call from
initState()
:You can now remove the data fetching from the
initState()
method:By making this adjustment, you should no longer see the error related to accessing Riverpod providers (or any InheritedWidgets) inside
initState()
.