Hey , I'm back , Randall Schwartz here with uh various dart and flutter tips for my dart and flutter channel .
Um Been seeing a question pop up rather frequently .
I look at stack overflow and Reddit and the Flutter community um uh Slack uh and another couple of other slacks and stuff .
And I was looking for questions .
I was trying to figure out what's going on .
And one of the things I've seen show up remarkably three times in three days is why isn't my future builder working or why isn't my stream builder work ?
Not working well .
I was playing around with it a little bit and I usually had the right answer like right away because there's a common mistake that you make with something like stream builder or future builder .
And they both apply the same way .
I'm gonna demonstrate it with stream builder because uh it's much more obvious what's going on and we can see the duration of time that the stream is a uh bypassing because it's putting out stuff every once in a while .
So I've taken the Venerable Counter app here and I've added a few lines to it .
So let's uh overlook .
Uh Let's look over , not overlook .
It's the opposite meeting .
Let's look over the lines that I've added to that .
One of them is this particular cool thing here .
So what I'm doing with this is I'm creating a stream of integers uh against a global function , name numbers uh from a global function name numbers .
And I'm doing this , I think rather cleverly , I actually like this uh approach stream periodic which will take a duration and a callback .
The duration here is one second .
That's the duration between the elements .
Now , this is an infinite list .
This is an infinite thing .
You have to shut it down somehow .
I've got my own way of shutting it down , but I'll get there in a second and then it calls this call back with a single parameter .
In this case , it's uh the numbers from zero to infinity .
If you just let it kept running , it would generate numbers up to infinity .
I won't be demonstrating that today .
Uh But I want actually one through 10 , not zero through whatever .
So I just add one to it .
And that's the value that gets returned as each event on this periodic stream .
Now , I've got that over here .
So that's the part that leads up to here .
My stream periodic .
And then I've got this other thing on here dot Take is a method on a number of different uh structures in dart .
Uh In this case on a stream , it says take that many values in this case 10 and pass them out as the output of the stream that take is creating internally .
You don't see that , but it's in there .
And as soon as it gets to that many items , it automatically uh quits and it quits taking the other stream with it and uh it closes down nicely .
There's no extra um stream closing we have to do .
So let's call this our function that we want to run uh and use the value of in our display .
The typical problem , right ?
We've got something that takes time .
This could just as easily be a future with uh maybe a um uh an HTP request or something like that .
But something that takes time in this case takes uh 10 seconds actually .
So uh that's the thing I wanna track .
So the naive way that I see people do and you'll see in a moment that it's wrong is that they go , OK ?
We want this stream to be here .
Now , this the rest of this is the counter app .
This is , this is nothing new down here .
All this stuff that's stuff you see all the time .
Uh But here this is added here , this stream builder and the stream builder takes a stream and we go , well , that's good .
Uh I have a stream , it's the stream that comes out of executing numbers .
And that's goes in there and then you put the builder function which has a context and a snapshot .
And for grins , I'm gonna be printing building SB building stream builder down here in the debug window at the bottom .
And then uh we're gonna go ahead and run this , uh and it's going to switch on connection state and if the state is none or waiting , it's just gonna spin that old circle .
Yeah , that's familiar circular progress indicator .
You're using it in a lot of places when you want a sync operations to be shown as a sync and then you've got connection state active .
And this is the good part .
This is where we're actually getting values in from the stream .
So we'll have data is , and you'll see in a moment it's data is one , data is two , data is three and so on .
Now when the stream finally exits finally says I'm done , then it calls back with connection state , done the uh um the stream stream builder calls back with and we'll just change that to done at and just to really make it stand out , I'll put an exclamation mark after that .
So this is the widget that people will typically create something that takes a stream or a future future builder would just have future appearance to the stream .
But the rest of this would actually all stay the same pretty much anyway .
And uh for some reason , of course , this always has to return a widget the builder has to return a widget .
So uh at the end , this line is never reached , but I just return a container to keep everybody happy .
Um It'll never execute this code though .
I could put , I could put a throw in there , I guess and really say it should not have been here .
Rest of the code , like I say is the same , all the same code from the standard Counter app .
Haven't done anything crazy now , just so we can start off in the middle and save some time .
I've actually launched this in debug mode and hit this run app as a , as a uh a break point .
So I'll turn the break point off and now I want you to watch over here on the right hand side .
So this is just after the app is up .
This is in that , that crazy white screen that everybody always complains about .
This is the thing you can fix by adding a splash screen .
And then I'm gonna go ahead and I know one of these icons means continue .
A couple things I want you to watch first off , it's gonna have the Counter app .
But above that will be the lines that come from the uh the uh stream builder .
So I think this is it F five .
There it is .
But look so yes , this is indeed updating uh 789 and so on .
Now , if I uh hot reload Uh I think that's how reload , reload and rest .
One of those is one of them .
Uh I'll do that one .
And again , notice as we start , we are uh we see the , the circular spin .
And watch for that because it's really important .
So now we've actually reached the end of our stream .
Our stream is happy .
We're at the end .
Uh we've shown all the values that we could show for it .
Let's increment the counter , watch carefully , watch carefully as I hit it .
Wait , why is the stream starting again ?
Why is this dream starting again ?
This is part of the problem and even more bizarre .
Suppose I wanna count quickly .
Suppose I hit two and then three and then four and then maybe 567 .
Look at that spinner .
Look how often that spinner keeps coming up .
We are restarting the stream from scratch every time we rebuild this page and you could see it in the footer building speed down here .
See , we've actually rebuilt that 41 times .
So this is a problem .
The reason this is a problem is suppose that was say , uh , a future that was going out and hitting a website .
Well , if you hit this plus button or you rebuild because you have an animation on the page , you're never gonna get that response back from that website .
It's not gonna work and this stream is not getting to 10 at any time .
See every time I hit build , it starts over .
And here's the problem .
So this is what people come to stack over with and , and all the other places that they can ask me questions .
I love questions .
By the way , it's not , that's not my complaint .
My complaint is I would like people to think about how they just used stream builder or future builder .
In this case , we've got stream of numbers .
This is going to get re executed every time we come into the build .
And what have I said over and over again in most of my comments that I make to people , imagine your build is being called 60 times a second and you don't want anything expensive in there .
You don't want anything that is changing state heavily .
You don't want anything like I owe and definitely you don't want a 12th stream builder or stream .
So here's what we need to do to fix it .
We should , instead of handing the stream from something that is constructing the stream , we should first take the stream .
Let's see where we've got it here .
Here it is .
We should take that stream .
This is inside the state of this state .
Full widget .
We should uncommon that code .
Now , what am I doing here ?
I'm building the stream and assigning it to a state variable .
I'm doing it during the constructor .
So I don't need to call set , set state .
It's already in the state and then what I do is come down here .
Uh Where is I went past it ?
Oh , I guess I get rid of it .
Oh , well , I got rid of the comments .
That's right .
So instead what you should do here , let's comment this out .
Now you gonna get to see me type .
I knew there was gonna be a time you could see me type and we're gonna pull up uh numbers the variable there .
Look at the difference here .
We're constructing the stream every time here , we're taking the value of this state variable called numbers , which is initialized once upon construction of the state to the output of our numbers uh stream creator .
Now what happens when we run this ?
Let me save it and let's see what happens when we do that first .
Uh Where does it go for ?
Oh OK .
So it's spun it , it held the 17 though .
That was nice and we're back .
We did one spin and then we had got all the way to 10 .
But watch increment 18 19 were not restarting the stream .
So that's the clue .
If you've got a future builder or a stream builder , don't construct the future or stream right there in the builder .
Instead , you need to move it out to a variable that you have access to or um you know , 11 of the uh like provider or a river pod or something like that river pod actually makes this even simpler , but I'm not gonna show that today .
Um And uh that , that does it .
Now we have this stream that is created only once and does our proper thing .
In fact , if we then hot restart this , I believe that's that right .
We'll see , um , we'll see the stream being fetched over again because it has to because everything is reset at that point .
So there we go 56789 10 .
And let's uh crank this up a few times and you'll , again , you'll notice 123 .
Yeah , no problem .
We're keeping the same stream and then uh let's do a hot reload .
I think that's the other one here when you hot reload , no visible change .
And even if we go in and say change pushed to you uh tapped the button .
So again , to show that we're staying done at 10 , even now when I hit save , there's my change there .
But once again , no reload of this dream .
So I hope that explains some of your um problems you've had with stream builder and future builder because they both work the same way .
Um I love questions .
Uh I want more ideas about what to do for videos .
So please leave that in the comments , subscribe .
Of course , I'll be like everybody else and there's so much other good stuff out there .
I gotta start linking some of my favorite channels to the uh page here to see uh what else I can talk about ?
All right , until later .
Uh , that's it for me .