Flutter StreamProvider<List<DogModel>> 无法分配
Flutter StreamProvider<List<DogModel>> can't be assigned
我收到以下错误 The argument type 'StreamProvider<List<DogModel>>' can't be assigned to the parameter type 'Stream<List<DogModel>>?'
当我尝试设置流时出现问题 stream: stream,
这里是小部件状态下的流
final stream = StreamProvider<List<DogModel>>(
create: (context) =>
DogFirestoreService().getDogs('GeVnAbdq9BWs1STbytlAU65qkbc2'),
initialData: const [],
);
小部件构建
Widget build(BuildContext context) {
//final test = context.watch<List<DogModel>>();
//print(test);
return SizedBox(
width: MediaQuery.of(context).size.width,
child: StreamBuilder<List<DogModel>>(
stream: stream,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Text('no data');
}
if (snapshot.hasError) {
return const Text('error');
}
if (snapshot.hasData) {
return SizedBox(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(
top: 65.0,
left: 18.0,
right: 18.0,
),
child: Text(
dogsCount(value.dogsList.length),
style: AppStyles.listsHeaderTextStyle,
),
),
ListView.builder(
padding: const EdgeInsets.only(
top: 5,
bottom: 20,
left: 15,
right: 15,
),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: value.dogsList.length,
itemBuilder: (context, index) => DogProfileCardWidget(
dogInfo: value.dogsList[index],
editProfile: openProfileScreen,
dogIndex: index,
),
),
],
),
);
}
return const Text('data');
},
),
);
}
}
你的问题是 stream
变量是 StreamProvider
.
StreamProvider
不是 Stream
,而是 Widget
。所以StreamBuilder
没看懂是什么
相反,您可能想这样做:
class Example extends StatefulWidget {
const Example({Key? key}) : super(key: key);
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
// The stream needs to be stored in a StatefulWidfet
// as you shouldn't create a new stream when the widget rebuild
final stream = DogFirestoreService().getDogs('GeVnAbdq9BWs1STbytlAU65qkbc2');
@override
Widget build(BuildContext context) {
return StreamBuilder<List<Dog>>(
stream: stream,
builder: ...,
);
}
}
您不需要 StreamBuilder
,因为您正在使用 StreamProvider
。此外,在您的代码中,您将 StreamProvider
放在哪里并不明显。顺便说一句,它是一个小部件,因此它应该位于示例中显示的小部件树上方。我看到您将其分配给 final stream = ...
,但我不确定为什么,因为它没有 return 流。
StreamProvider
将订阅您提供的流(即 DogFirestoreService().getDogs('...')
),一旦数据到达,它就会沿着树向您提供(最初,它会提供initialData
).
我在 DartPad 上做了一个简单的例子,你可以在这里查看:
Stream Provider Example.
将 StreamProvider
小部件放在感兴趣的小部件上方后,在 build
方法中,您可以像这样直接访问数据:
final data = context.watch<List<DogModel>>();
在第一个构建中,你会得到你给 StreamProvider
的 initialData
,这是一个空列表。所以你可以这样做:
@override
build(BuildContext context) {
final data = context.watch<List<DogModel>>();
if (data.isEmpty) {
return const Text('no data');
}
return SizedBox(/* the rest of your code */);
}
我收到以下错误 The argument type 'StreamProvider<List<DogModel>>' can't be assigned to the parameter type 'Stream<List<DogModel>>?'
当我尝试设置流时出现问题 stream: stream,
这里是小部件状态下的流
final stream = StreamProvider<List<DogModel>>(
create: (context) =>
DogFirestoreService().getDogs('GeVnAbdq9BWs1STbytlAU65qkbc2'),
initialData: const [],
);
小部件构建
Widget build(BuildContext context) {
//final test = context.watch<List<DogModel>>();
//print(test);
return SizedBox(
width: MediaQuery.of(context).size.width,
child: StreamBuilder<List<DogModel>>(
stream: stream,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Text('no data');
}
if (snapshot.hasError) {
return const Text('error');
}
if (snapshot.hasData) {
return SizedBox(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(
top: 65.0,
left: 18.0,
right: 18.0,
),
child: Text(
dogsCount(value.dogsList.length),
style: AppStyles.listsHeaderTextStyle,
),
),
ListView.builder(
padding: const EdgeInsets.only(
top: 5,
bottom: 20,
left: 15,
right: 15,
),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: value.dogsList.length,
itemBuilder: (context, index) => DogProfileCardWidget(
dogInfo: value.dogsList[index],
editProfile: openProfileScreen,
dogIndex: index,
),
),
],
),
);
}
return const Text('data');
},
),
);
} }
你的问题是 stream
变量是 StreamProvider
.
StreamProvider
不是 Stream
,而是 Widget
。所以StreamBuilder
没看懂是什么
相反,您可能想这样做:
class Example extends StatefulWidget {
const Example({Key? key}) : super(key: key);
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
// The stream needs to be stored in a StatefulWidfet
// as you shouldn't create a new stream when the widget rebuild
final stream = DogFirestoreService().getDogs('GeVnAbdq9BWs1STbytlAU65qkbc2');
@override
Widget build(BuildContext context) {
return StreamBuilder<List<Dog>>(
stream: stream,
builder: ...,
);
}
}
您不需要 StreamBuilder
,因为您正在使用 StreamProvider
。此外,在您的代码中,您将 StreamProvider
放在哪里并不明显。顺便说一句,它是一个小部件,因此它应该位于示例中显示的小部件树上方。我看到您将其分配给 final stream = ...
,但我不确定为什么,因为它没有 return 流。
StreamProvider
将订阅您提供的流(即 DogFirestoreService().getDogs('...')
),一旦数据到达,它就会沿着树向您提供(最初,它会提供initialData
).
我在 DartPad 上做了一个简单的例子,你可以在这里查看: Stream Provider Example.
将 StreamProvider
小部件放在感兴趣的小部件上方后,在 build
方法中,您可以像这样直接访问数据:
final data = context.watch<List<DogModel>>();
在第一个构建中,你会得到你给 StreamProvider
的 initialData
,这是一个空列表。所以你可以这样做:
@override
build(BuildContext context) {
final data = context.watch<List<DogModel>>();
if (data.isEmpty) {
return const Text('no data');
}
return SizedBox(/* the rest of your code */);
}