我不明白为什么我的FutureProvider不能正常运行,而ChangeNotifierProvider却可以正常运行。
无论我做什么,即使我删除ChangeNotifierProvider并将其替换为FutureProvider或将我的MaterialApp小部件包装为FutureProvider或用户MultiProvider也会给我同样的错误。
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);
}),
);
}
}
这是错误
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>()),
}
),
}
答案 0 :(得分:0)
我发现了这个问题,在声明FutureProvider时提供类型是一个愚蠢的问题。
只需更改此内容即可
// --- client ---
FileDescriptorProto local_proto = request->custom_proto(); //this is from the server
//const google::protobuf::Descriptor* message_desc = local_proto.GetDescriptor();
DescriptorPool pool_;
const FileDescriptor* local_proto_;
local_proto_ = pool_.BuildFile(local_proto);
// display message contents
const google::protobuf::Descriptor* message_desc = local_proto_->FindMessageTypeByName("AttribRow");
cout << "Field Count: " << message_desc->field_count() << endl;
google::protobuf::DynamicMessageFactory factory;
const google::protobuf::Message* mutable_msg = factory.GetPrototype(message_desc);
const Reflection* reflection = mutable_msg->GetReflection();
const Descriptor* descriptor = mutable_msg->GetDescriptor();
for (int i = 0; i < descriptor->field_count(); i++) {
const FieldDescriptor* fd = descriptor->field(i);
cout << fd->name() << " -> " << reflection->GetInt64(*mutable_msg, fd) << endl; //this fails
}
对此:
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(),
],
),
);
}
}