Close Dart Stream that doesn't use StreamSubscription? - flutter

I have a simple function that returns a Stream. Works great:
Stream<List<User>> streamPeopleToFollow({#required User startAfterUser}) {
Query query = _usersRef.orderBy('dateTime', descending: false).limit(20);
if (startAfterUser != null) 
query = query.startAfter([startAfterUser.dateTime.toIso8601String()]);
return query.snapshots().map((snapshot) {
return snapshot.docs.map((doc) {
return User.fromJson(doc.data());
}).toList();
});
}
I give to a StreamBuilder:
:
return StreamBuilder(
stream: streamPeopleToFollow(startAfterUser),
builder: (context, snapshot) {
:
When "startAfterUser" changes, the widget with the StreamBuilder rebuilds and I get my updated list, so the old stream is abondoned. This all is working fine. My question is about the disposed Stream--I don't see any "close" or "cancel" functions in the Stream class. Does it close when its disposed? I obviously want to avoid dangling streams.

Related

Same streambuilder on next page but it stucks on ConnectionState.waiting

I am using bloc. But I found very rare issue i.e Stream is working well on one page but at the same time when we navigate to another page it is showing in ConnectionState.waiting
Here is my piece of code:
In bloc:
late StreamController<String> _timeRemainingController=StreamController.broadcast();
Stream<String> get timeRemainingStream => _timeRemainingController.stream;
// While adding value:
_timeRemainingController.add("");
Here is streambuilder which I am using
StreamBuilder<String>(
stream: _clockTimerBloc.timeRemainingStream,
builder: (context, snapshot) {
if (snapshot.hasData) {
//code
}
Common code which used everywhere. I am stuck there Please try to check. And thanks for any response.

Rebuild FutureBuilder from another widget

Right now, I am using a FutureBuilder to build a list of activities. But the activities have a timer, using CountdownTimerController, which runs down to 0. I want to change the list and update the list onEnd of the timer. But the timer widget is on a different file overall. How could I do the needful?
FutureBuilder(
future: fetchUserActivities(),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.done) {
if (snapshot.hasError) {
return Center(
.....
What should I change in this or add in OnEnd function of the timer to update the list?
you should embed your list in an other FutureBuilder inside the the one you use to fetch activities. Or put each list in a Statefull widget and call a setState by the end of your timer.
According to your comment, an easy way will be using a state management package like RiverPod, put your timer in a ChangeNotifier and use Consumer widget in your other page.

How to listen for state changes inside a FutureBuilder widget and reflect the state change?

to demonstrate the problem, let me write down some code for a FutureBuilder.
FutureBuilder(future: _myFuture, builder: (context, snapshot) {
if(snapshot.hasData) {
// !!!! IMPORTANT !!!
// Pay attention to the _isFirstText variable below
return SizedBox(
child: _isFirstText ? Text(snapshot.data.firstText) : Text(snapshot.data.secondText),
);
}
if(snapshot.connectionState == ConnectionState.isWaiting) {
return Text('Waiting!');
}
return Text('Error');
}),
As I have mentioned in a comment in the above code, pay attention to the _isFirstText variable. Suppose that is a state variable. Inside the future builder, how do I get the correct return value that corresponds to the isFirstText state variable change.
I also came across this stack overflow post but could not get the code to work.
I also came across a widget called StatefulBuilder, but I can not figure out to where in my FutureBuilder I should use it.
Can someone please help?
If you want to listen to ongoing changes you can use a Streambuilder. Streams are not only for serverside changes but can also be used locally.
You can build a Stream yourself like this :
StreamController myStreamController = StreamController<int>();
To send a new event through this controller you can do
myStreamController.sink.add(newValue);
You can then listen to changes like this:
#override
Widget build(BuildContext context) {
return StreamBuilder<int>(
stream: myStreamController.stream,
builder: (context, snapshot) {
final value = snapshot.data;
return Text(value!.toString());
}
If you want to learn more check this Video: https://youtu.be/nQBpOIHE4eE
Let me know if this helped.
You can use ValueNotifier variables and use notifyListeners() to update a specific parts of your code Like this:
ValueListenableBuilder and use that ValueNotifier variable and listen to that.

Is there way to get a callback after StreamBuilder completely load?

I'm trying get a callback after my context build, i already tried with "WidgetsBinding.instance!.addPostFrameCallback", but not works because i have a StreamBuilder and the first load of snapshot data it is null.
I expected exists a callback of StreamBuilder after data completely load and build loaded, here is my code:
StreamBuilder(
stream: this.paymentInfoFormPresenter.key,
builder: (context, snapshot) {
final _formKey = snapshot.data;
if (_formKey == null) {
return Container();
}
return Text('example');
}
);
And i don't find anything about on internet... i hope someone can help me.
To resolve this issue, i needed change the "Text('example')" to an external widget, and added "WidgetsBinding.instance!.addPostFrameCallback" inside of this external widget

Convert a Stream to a Future in Flutter

a Flutter beginner here so if my question is stupid don't mind it...
How can I convert a Stream to a Future?
I have a Stream that just calls the requested URL multiple times because it's a Stream. I want to be able to get the data and not the loading state... Because I always just get loading forever
Is there something like Future.fromStream() function somewhere and I'm missing it?
Can I achieve this?
I didn't provide any code because I think it's not needed if you need the code, I can edit the question
Stream has firstWhere method, this will return Future
_profileService.profileStream.firstWhere((element) => false);
Stream and Future are two different concepts.
As you are using, stream is keeping the data updated, and Future is just one time.
Example of using stream: Shopping Cart, listing of items
Example of using future: getUserDetails after login.
If you're using stream, then you can use streambuilder to build your UI
StreamBuilder<User>(
stream: userBloc.author, // your stream here
builder:
(BuildContext context, AsyncSnapshot<User> snapshot) {
if (snapshot.connectionState == ConnectionState.active && snapshot.hasData) {
// do your work here
} else {
return CircularprogressIndicator();
}
},
)