I'm getting the following error The argument type 'StreamProvider<List<DogModel>>' can't be assigned to the parameter type 'Stream<List<DogModel>>?'
Happing when I try to set the stream stream: stream,
Here the stream in the widget state
final stream = StreamProvider<List<DogModel>>(
create: (context) =>
DogFirestoreService().getDogs('GeVnAbdq9BWs1STbytlAU65qkbc2'),
initialData: const [],
);
And the widget build
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');
},
),
);
} }
CodePudding user response:
Your problem is that the stream variable is a StreamProvider.
StreamProviders are not Streams, they are Widgets. So StreamBuilder does not understand what it is.
Instead you may want to do:
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: ...,
);
}
}
CodePudding user response:
You don't need StreamBuilder since you're using StreamProvider. Also, it's not obvious on your code where are you placing the StreamProvider. It's a widget by the way so it should be on the widget tree above the one shown on your example. I see you're assigning it to final stream = ... but I'm not sure why because it does not return a stream.
StreamProvider will subscribe to the stream you gave (i.e., DogFirestoreService().getDogs('...')) and once the data arrives, it'll provide it to you down the tree (initially, it'll provide the initialData).
I made a simple example on DartPad that you can view here: Stream Provider Example.
Once you place the StreamProvider widget above the widget of interest, then in your build method you can access the data directly like this:
final data = context.watch<List<DogModel>>();
In the first build, you'll get the initialData you gave to StreamProvider which is an empty list. So you can do:
@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 */);
}
