Contrast
< Back to Blog
Original link:

https://youtu.be/sqE-J8YJnpg

2023-08-19 23:34:21

Fixing a common FutureBuilder and StreamBuilder problem

video content Image generated by Wilowrid

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 .

video content Image generated by Wilowrid

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 .

video content Image generated by Wilowrid

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 .

OK .

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 .

video content Image generated by Wilowrid

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 .

OK ?

So let's call this our function that we want to run uh and use the value of in our display .

OK .

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 .

video content Image generated by Wilowrid

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 .

OK ?

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 .

video content Image generated by Wilowrid

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 .

Right .

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 .

OK ?

video content Image generated by Wilowrid

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 .

OK ?

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 .

video content Image generated by Wilowrid

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 .

OK ?

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 .

OK ?

There it is .

But look so yes , this is indeed updating uh 789 and so on .

OK ?

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 .

OK .

Yeah .

video content Image generated by Wilowrid

And again , notice as we start , we are uh we see the , the circular spin .

OK .

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 .

video content Image generated by Wilowrid

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 .

Right .

See every time I hit build , it starts over .

OK ?

And here's the problem .

OK ?

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 .

video content Image generated by Wilowrid

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 .

video content Image generated by Wilowrid

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 ?

Ok .

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 .

OK .

Look at the difference here .

video content Image generated by Wilowrid

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 .

video content Image generated by Wilowrid

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 .

Ok .

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 .

video content Image generated by Wilowrid

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 .

video content Image generated by Wilowrid

Uh , that's it for me .

Partnership

Attention YouTube vloggers and media companies!
Are you looking for a way to reach a wider audience and get more views on your videos?
Our innovative video to text transcribing service can help you do just that.
We provide accurate transcriptions of your videos along with visual content that will help you attract new viewers and keep them engaged. Plus, our data analytics and ad campaign tools can help you monetize your content and maximize your revenue.
Let's partner up and take your video content to the next level!
Contact us today to learn more.