I fail to understand why my FutureProvider fails to whereas my ChangeNotifierProvider works perfectly.
No matter what I do, it gives me the same error, even if I remove my ChangeNotifierProvider and replace it with FutureProvider or wrap my MaterialApp widget with FutureProvider or user MultiProvider, it gives me the same error.
import 'package:provider/provider.dart';
import 'package:sprightly/new/Constants.dart';
import 'package:sprightly/new/ConstraintProvider.dart';
import 'package:sprightly/new/SearchBox.dart';
import 'package:sprightly/new/api/ApiService.dart';
import 'package:sprightly/new/model/ServerResponse.dart';
import 'package:sprightly/new/profile/Profile.dart';
class Home extends StatelessWidget {
const Home({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: green,
elevation: 0,
),
body: Background(),
);
}
}
class Background extends StatelessWidget {
double width(double width) {
return width > 500 ? width * 0.6 : width;
}
void setConstraints(BuildContext context, BoxConstraints constraints) {
Provider.of<Constraint>(context, listen: false)
.setHeight(constraints.maxHeight);
Provider.of<Constraint>(context, listen: false)
.setWidth(constraints.maxWidth);
}
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => Constraint(),
child: LayoutBuilder(builder: (context, constraint) {
setConstraints(context, constraint);
return Stack(
children: [
Column(
children: [
Container(
width: double.infinity,
height: MediaQuery.of(context).size.height * 0.20,
color: green,
child: Align(
alignment: Alignment.centerRight,
child: Image.asset(
'assets/images/backdrop.svg',
),
),
),
],
),
Center(
child: Padding(
padding: EdgeInsets.only(
top: MediaQuery.of(context).size.height * .10,
),
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
child: Container(
width: width(constraint.maxWidth),
color: Color(0xffF0F0F0),
child: Foreground(),
),
),
),
),
],
);
}),
);
}
}
class Foreground extends StatelessWidget {
final ApiService api = ApiService();
@override
Widget build(BuildContext context) {
return FutureProvider(
create: (context) => api.getServer(),
catchError: (context, error) => print(error.toString()),
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(
top: 20,
left: 20,
right: 20,
),
child: SearchBox(),
),
SizedBox(
height: 10,
),
ServerList(),
],
),
);
}
}
class ServerList extends StatelessWidget {
@override
Widget build(BuildContext context) {
ServerResponse response = Provider.of<ServerResponse>(context);
return Expanded(
child: ListView.builder(
itemCount: response.response.length,
itemBuilder: (context, index) {
var width = Provider.of<Constraint>(context).getWidth();
print(width);
return Profile(index);
}),
);
}
}
this is the error
Error: Could not find the correct Provider<ServerResponse> above this ServerList Widget
This likely happens because you used a `BuildContext` that does not include the provider
of your choice. There are a few common scenarios:
- The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then
other routes will not be able to access that provider.
- You used a `BuildContext` that is an ancestor of the provider you are trying to read.
Make sure that ServerList is under your MultiProvider/Provider<ServerResponse>.
This usually happen when you are creating a provider and trying to read it immediatly.
For example, instead of:
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// Will throw a ProviderNotFoundError, because `context` is associated
// to the widget that is the parent of `Provider<Example>`
child: Text(context.watch<Example>()),
),
}
consider using `builder` like so:
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// we use `builder` to obtain a new `BuildContext` that has access to the provider
builer: (context) {
// No longer throws
return Text(context.watch<Example>()),
}
),
}