Flutter Tutorial - Adding Pagination with a NotificationListener widget and ScrollNotifications
Skills:
Prompt Craft80%Tool Use & Function Calling80%Prompt Systems Engineering70%Advanced Prompting60%Agent Foundations50%
Key Takeaways
This video tutorial demonstrates how to implement pagination in a Flutter application using a NotificationListener widget and ScrollNotifications, with tools such as Flutter, NotificationListener, HTTP, Provider, and RxDart.
Full Transcript
hey guys my name is tensor welcome to another frontier tutorial video today we're going to be looking at pagination and we'll be looking at a widget called a notification listener we're going to be covering pagination in flutter because a lot of you guys have asked me to make a tutorial on this subject now for those of you who do not know what pagination is I've got a nice little example here this is written by another individual by the name of Tim and I can't pronounce his last name and it's essentially just an infinite scroll with pagination the idea here is that as we scroll down it will then go ahead and call to whatever API it's calling to get more of these pictures and it'll look like we can just continuously scroll without interruption because the responses are hidden behind these pages and you can see right here that they've actually got the pages numbered so we've scrolled down five pages thus far and once we hit the sixth one you'll see that a sixth number will appear down here at the bottom now in our example we will not have numbers like this but we will be loading our data dynamically as we scroll down our list view the API that we're going to be using is the JSON placeholder API and we're going to be using the photos route because it has five thousand items inside of it now the JSON structure for this is pretty simple we've got an album ID an ID a title a URL and then a thumbnail URL and we're going to define pages based on the album ID and in this API 50 items are labeled as number one in the upper ID and then there are another 50 in album ID two and so on and so what we're going to do is essentially just pull in the JSON 50 items at a time and then serve it to the ListView before we get started with our code we want to bring in a few imports so we're going to be calling to the API so we need the HTTP library then we're going to be building a block so I'm going to bring in provider so that we can serve the block to our widget tree and then we're going to be working with streams so I will be bringing in our exit and all of these are using the latest version at the time of this video recording let's go ahead and create a class for our photos each one of them will have a integer ID and integer album ID and then three strings one for the title one for the URL and then one for the thumbnail URL so we've created a constructor we then of course want to create a constructor and then we also want to create a named constructor so that we can take this data and decode it from the JSON and of course our name constructor will just take in a map and then we'll just grab each of the items based on their respective JSON key so ID will be ID album ID will be album ID and so on with our model settled we can go ahead and create our Network API class so I've created a file here called network dirt I've imported the HTTP library dark convert and of course our model and let's go ahead and define our API class and I'm going to put a string for the URL inside of it and our URL is just going to go to the photos route of the JSON placeholder API so what we want to do is create a function here which will return a future list of photo and it will take in an integer for the album ID if we quickly go back to our API you can see here that if I type in question mark album ID equals and then add a number in this case one I'll get only the items from this specific album ID and so this will act like our first request and our first page so rather than pulling in all 5,000 of the JSON items we're just going to pull in the first 50 so we want to go ahead and create a get request and what we'll do is we'll take our URL and we'll use string interpolation to add the question mark album ID equals the album ID that we're passing in here and of course we'll then parse that as a URI and pass it into HTTP GET this will give us back our response then we can take that sponsz pass it through our JSON decode function this will give us back a list of map and we can then go ahead and map over this JSON data and take each of the JSON objects or each of the maps rather and pass them through our photo from JSON named constructor and then of course we want to pass this back as a list all right so now we have our model and our network set up let's go ahead and create our block so I've created a file here called block dirt I brought in the dirt async library I brought in the flutter widgets library and you'll see why we need that in a moment and I've also brought in our model and our network API and then I've brought in our X dart so we'll create a class here called photo block and inside of it we want to create a few fields first we want to instantiate our API so that we can call it inside of the block and then we also want to create an integer for our page number so that we can hold the state of the current page that were calling from our API now for our example we're going to need to stream controllers and I'm going to use the replay subject from our X dart instead of just a normal stream controller for both of these so the first one will be our output which will be a list of photos and we'll be passing this back to the UI but we'll also have a sink here and the idea is that the output of this other replay subject will be pushed into this stream and then it will be converted into a list of photographs this second replay subject is a replay subject of scroll notifications now scroll notifications are essentially just notification events that we get back as we're scrolling through our ListView and we're going to use what's called a notification listener to be able to pass those events back to the block the basic idea is that we want to find out when the list is at a certain point specifically when it hits the bottom of our list and of course we want to take both of these replay subjects and close them inside of a dispose function so that we do not have a memory leak now we can go ahead and define all of our business logic inside of the constructor of this block so we're going to directly call our API die get photos to pass this in to our subject stream so we can call a subject add stream and then we want to convert the future from API get photos into an observable so we can use observable from stream to do this and we'll call our API dot get photos with the page number that we have up here the main reason that we're calling this first is so that we get the first request from our API when the application loads up if we do not make this call then we'll have a list that doesn't have any items inside of it and as a result we will not have any scroll notifications to listen on and so then we can't make any further API calls the main logic for our block is going to reside inside of this load photos function and the load photos function will pass back a feature of void and it will take in a squirrel notification there are a lot of different notifications that we're going to get from our UI so we want to check that we have the specific notification that we want to call the API that way we don't overload and call the API multiple times without actually being at the place where we want to call it so we can use the notifications metrics to find out where we are in pixels along the axis of our ListView and then we can see if that is equal to the max scroll extent the max scroll extent of course is just the bottom of our list view when we hit the bottom of ListView this will fire off and then we can call to our API first we'll take our page number value and we'll increment it and we're doing this because we did originally call to the API first above where we're going to call this load photos function this is calling page 1 and then we want to call page 2 so we increment it first before we go ahead and call the API a second time then we can just take the list that we're getting back from the API and pass it into our subject sink so that we can then serve it out to the stream finally we want to tie our two streams together and we can do this by adding a listener to our controller replay subject and this will just take each of the notification events that are being passed through this replay subject and pass it into our load photos function which will then of course call to our API and pass the data into our other stream there are two more items that we want to add to our block so we want to add a getter for our stream so this is just the subject stream and then we want to add a getter for the sink for our controller so the sink will allow us to pass in scroll notification events and then the stream will allow us to receive the lists of photos from our API calls all right so now we have all of the backend finished for our application let's go ahead and build the graphical user interface we need to bring in the model and the block and of course we also want to bring in provider let's first start by injecting our block at the top of our widget tree so we're just going to wrap the material app inside of a provider widget and then add a builder function which is calls to the photo block constructor and then a dispose function which we'll just call block dot dispose all right so now let's come down to our my home page and this is going to be a stateful widget though you could probably get away with a stateless widget if you wrote it properly inside of our state object we want to define a few fields so I'm creating a list of photo called photos and this is going to hold all of our photos and then I'm going to also create a list called max photos which will be a list of integers and we can use it to basically know how many items are inside of the API we want to then initialize both of these fields inside of in its state so for max photos I'm just going to call list dot generate to generate a list that will have a length of 5000 and it will have numbers from 0 all the way up to 4 9 9 9 and then for the photos I'm just going to set it equal to an empty list all right so let's come down to our scaffold for the body we're going to create what's called a notification listener widget and we're specifically looking for scroll notifications so we can pass that in as the parameterised literal type for this widget this widget just contains a child field and then a on notification callback function which passes back a boolean and takes in a function that takes in a scroll notification all right so let's go ahead and create the on notification callback function and I'm going to cheat a little bit here and actually pass in our photo block the function itself is pretty simple we just want to check to see if the scroll notification is an over scroll event this means that the user has tried to essentially over scroll the ListView so by filtering out each of our scroll events by over scroll notification we can limit the amount of items that were passing through our stream sink so then we'll just take each of our over scroll notifications and we'll pass them into the block sink by calling block sink dot add then after we run our little if check we're just going to return false from this function and what that does for us is it makes it so that none of these scroll events from our ListView will proliferate further up our widget tree from this widget now we can take the on notification function and call it in the on notification property of the notification listener and of course for this we need to grab our block so we can grab it by calling provider of photo block and then pass in the build context we just want to create a small closure which will get the notification event and pass it into on notification along with the block the child of our notification listener will be a stream builder in the stream that we're going to listen on will be our block stream and of course this will just be type list photo and then that means that the Builder function will have the context and then an async snapshot of list photo and so what we can do is then just return a call to a function that will build called build ListView which takes in the context and the snapshot our build ListView function takes in the context and the async snapshot and then it will return a widget and the first thing that we'll do inside of it is check to see whether or not the snapshot has data and if it doesn't have any data then we just want to show a circular progress indicator and if it does have data then we'll create our ListView and we can use a ListView builder for this because the ListView will be growing we want to specify the item count of our ListView builder so initially we'll have an item count of 50 but actually as you see here we'll actually have an item count of 51 and this will make a little bit more sense as we continue down item count will be a check to see if max photos length is greater than our photos length which as we know our max photos is a length of 5,000 and then the initials photos length will be a length of 50 so if this is true then we'll return photos length plus 1 which means 51 otherwise we'll just return photos length now we can go ahead and add our item builder to our ListView builder and we're going to output a list tile or we're going to output a container with a circular progress indicator inside of it so what we can do is check to see what our current index is and check to see if that index is equal to the length of our photos list that allows us to add a circular progress indicator to the bottom of the list when we're calling to the API this is why we have a length of 51 even though our photos list will have a length of 50 on the initial call what will happen is we'll have 50 items which will be list tiles with our information inside of it and then when we get to number 51 we'll have a circular progress indicator down there which will appear until the length of our photos list increases because of our call to the API finally we can go ahead and define how we want our data to look inside of the list tile so we can go ahead and have a circular avatar with an image network and we can use the thumbnail URL to add that image there and that will be the leading item of the list I'll then the title will be our ID and then the subtitle will be the title of the picture and there's one final thing I want to add to the app before we go ahead and run it and that is this call in here after we check to see if the snapshot has data or not we'll call photos dot add all and then we'll add in all of these snapshot data and the photos list will basically act as an alias for our snapshot data and it will allow us to you and it will allow us to keep all of the data from each of our API calls so that even if the user Scrolls down to say two thousand they can scroll all the way back up to page one I also want to go ahead and add a print statement to the top of our on notification function so that we can see all of these scroll in events that come through as we scroll through on list view this way I can show you the different events that happen through the lifecycle of a ListView there are two tiny mistakes that I made while coding this app so I forgot to add the parameterize type annotation to the provider so you want to make sure to add this here so provider of photo block type and then I also didn't add an initialization for the max photos so when I called at all you're calling it on a null list the other way to do it of course would just be to set max photos equal to list generate and here's our application inside of the emulator so as you can see as we scroll down we get all of the different scroll notifications the most common of which is this scroll update notification then when we stop scrolling we get a scroll and notification and then we also get a user scroll notification well let's keep scrolling until we get down to 50 and once we hit 50 you can see that we have our circular progress indicator and then we get 51 and now we can continue scrolling all the way down to 100 before it will load again and once we hit 100 you can see that it will load another page and then when we hit 150 it'll go to load another page yet again now there is one minor flaw with the way that we're doing this the problem here is that when we scroll through and we hit the edge of one of our pages the user can actually issue more than one scroll notification of type over scroll if the API takes too long to load the page we can fix this by adding a little logic to our block and add another field here called pixels and it will be a double which I'll set equal to zero point zero by default with this field we can then come down to our load photos function and add a extra conditional to our if statement so we're going to add this using an and we want to check to see if the pixels field is not equal to the notification metric dot pixels value and then after we call this if check we want to take our pixels value and set it equal to notification metric pixels when we scroll to the bottom of one of our pages we'll get our over squirrel notification and let's say two of them are being sent through the first one will come through and the value of pixels will be 0.0 or whatever the last pages max scroll extent was and that value will not be equal to the new notification metric pixels value then we can use this to reset the value so when the second notification event comes through it doesn't pass this conditional and therefore it doesn't call to our API so now even if I scroll through here a lot and I pull up a lot on the list it will not try to call the API multiple times and flood our sink with a bunch of buffered API calls oh and by the way just so that you guys can see we've scrolled up to 350 this would go up to 400 if we scroll all the way back down we still have all of the other values in the list all right guys well I hope you enjoyed this tutorial if you did feel free to like and subscribe if you have any questions or comments feel free to leave them in the box below and if you just like this video then by all means download it as much as you like if you want to catch other flutter videos then go ahead and hit that notification though have a good night
Original Description
#Flutter #TensorProgramming #FlutterPagination
In this Tutorial, we look at how to implement Pagination in a simple API BLoC example. We use a Notification Listener Widget and Scroll Notifications to accomplish this task. We also use Bloc, Provider and RxDart in this example.
Source Code for this example: https://github.com/tensor-programming/flutter-pagination-tutorial
Good Programming Laptops:
Lenovo ThinkPad E570: https://amzn.to/2TFEiVG
Dell XPS15: https://amzn.to/2RxyavP
Support the Channel and Join Patreon:
Patreon: https://www.patreon.com/tensor_programming
Dontate:
ETH: 0x03247265dd5242605bD2FA3c40fb3b70d9e3D685
Cardano: addr1q9auccwrr9ws8qdyv45f4qwsx76pfmld4zapks89sakq94ay0xmle73y0r8ruwd0zslls4eglf98lghru7ywv56cedysk7ftjt
Check out our Twitter: https://twitter.com/TensorProgram
Check out our Facebook: https://www.facebook.com/Tensor-Programming-1197847143611799/
Check out our Steemit: https://steemit.com/@tensor
Watch on YouTube ↗
(saves to browser)
Sign in to unlock AI tutor explanation · ⚡30
Playlist
Uploads from Tensor Programming · Tensor Programming · 0 of 60
← Previous
Next →
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
NodeJs, Text editors and IDEs
Tensor Programming
Vanilla JS todo App
Tensor Programming
Elm Tutorial part 1
Tensor Programming
Elm Lang Tutorial, Part 2
Tensor Programming
Elm Tutorial Part 3
Tensor Programming
Elm Tutorial Part 4 -- Analog Clock App
Tensor Programming
Elm Tutorial part 5 -- Snake Game
Tensor Programming
Elm Tutorial part 6 -- Calculator
Tensor Programming
Go Tutorial part 1 -- Hello World and Static File Server
Tensor Programming
Go Tutorial part 2 -- Web Crawler
Tensor Programming
Go Tutorial Part 3 (Web App part 1)
Tensor Programming
Go tutorial Part 4 (Web tutorial part 2) - Using templates
Tensor Programming
Go tutorial part 5 (web app part 3)
Tensor Programming
Go tutorial part 6 (webapp part 4)
Tensor Programming
Go tutorial part 7 (web app part 5)
Tensor Programming
Go tutorial part 8 (Web app part 6)
Tensor Programming
Go tutorial Part 9 (web tutorial part 7)
Tensor Programming
Go tutorial Part 10 (web app part 8)
Tensor Programming
Go tutorial Part 11 (Web app Part 9)
Tensor Programming
Go Tutorial Part 12 (Web app Part 10)
Tensor Programming
Go Tutorial Part 13 (Web app Part 11)
Tensor Programming
Looking at Elm 0.18
Tensor Programming
Go tutorial Part 14 (Web tutorial part 12)
Tensor Programming
Go tutorial Part 15 (Web tutorial part 13)
Tensor Programming
Go tutorial part 16 (web app part 14)
Tensor Programming
Elm Tutorial Part 7 (SPA part 1)
Tensor Programming
Elm Tutorial Part 8 (SPA Part 2)
Tensor Programming
Electron Elm Tutorial
Tensor Programming
Go tutorial part 17 (web app part 15)
Tensor Programming
Up and Coming Programming Languages and Technologies for 2017
Tensor Programming
elixir tutorial part 1
Tensor Programming
elixir tutorial part 2
Tensor Programming
Elixir tutorial Part 3 (GenServer and Supervisor)
Tensor Programming
Elixir Tutorial Part 4 (GenStage)
Tensor Programming
Elixir Tutorial Part 5 (Plug and Cowboy)
Tensor Programming
Phoenix Framework Tutorial Part 1 (elixir part 6)
Tensor Programming
Phoenix Framework Tutorial Part 2 (elixir part 7)
Tensor Programming
Phoenix Framework Tutorial Part 3 (elixir part 8)
Tensor Programming
A Intro to Clojure and Clojure Syntax
Tensor Programming
An Update about the channel
Tensor Programming
Intro to Rustlang (Setup and Primitives)
Tensor Programming
Intro to Rustlang (Strings, Tuples, Arrays, Slices and Pretty Printing)
Tensor Programming
Intro to Rustlang (Ownership and Borrowing)
Tensor Programming
Intro to Rustlang (Structs, Methods, Functions, Related Functions and the Display/Debug Traits)
Tensor Programming
Intro to Rustlang (Control Flow, Conditionals and Pattern Matching)
Tensor Programming
Intro to RustLang (Enums and Options)
Tensor Programming
Intro to Rustlang (Vectors, HashMaps, Casting, If-Let, While-Let, and the Result Enum)
Tensor Programming
Rustlang Project: Snake Game
Tensor Programming
Intro to Rustlang (Traits and Generic Types)
Tensor Programming
Intro to Rust-lang (Closures, the Box Pointer and Iterators)
Tensor Programming
Intro to Rust-lang (Modules and Lifetimes)
Tensor Programming
Intro to Rust-lang (Macros and Metaprogramming)
Tensor Programming
Intro to Rust-lang (Error Handling)
Tensor Programming
Intro to Rust-lang (Concurrency, Threads, Channels, Mutex and Arc)
Tensor Programming
Intro to Rust-lang (Tests, Attributes, Configuration and Conditional compilation)
Tensor Programming
Rustlang Project: Port Sniffer CLI
Tensor Programming
Rustlang Project: Chat Application
Tensor Programming
Rustlang Project: CLI Toy Blockchain
Tensor Programming
Intro to Rust-lang (Setting up a Development Environment)
Tensor Programming
Intro to Rust-lang (Building a Web API with Iron)
Tensor Programming
More on: Prompt Craft
View skill →Related AI Lessons
⚡
⚡
⚡
⚡
How to prepare TIC teacher exams in Spain with AI (oposiciones 2026)
Dev.to AI
Why I built a simple AI provider wrapper (and you might too)
Dev.to · zhongqiyue
This ChatGPT Prompt Replaced 3 Hours of PowerPoint Work
Medium · AI
This ChatGPT Prompt Replaced 3 Hours of PowerPoint Work
Medium · ChatGPT
🎓
Tutor Explanation
DeepCamp AI