Pagination in Flutter with BLoC/Cubit

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video i'm going to show you how to implement pagination in flutter with the block pattern we will use the flutter block library and it has something called as a qubit which is an extension over the block and it makes the implementation of the block pattern simpler and faster pagination helps in creating better performant network dependent apps so if an app fetches a lot of data from the internet and shows them in a list then paginating that list will make the app faster with pagination we fetch small chunks of data from the internet and we show it in the app and anything that the user might not see is not fetched which reduces the amount of data that we are getting from the internet and when a user scrolls a list of data to the end then we make another request to get the next set of data and when we receive that data we add it to the list and the user can then interact with it pagination overall contributes to a better user experience and we are going to implement it today you can find the code of this video in a github repo i have it linked in the description now let's get started we will use this jsonplaceholder.typeecode.com to get a fake json array that we will be paginating in our app and this json placeholder has this posts route that we will be using in the app and if we go here then we can see that we have around 100 json objects but we will not be fetching all of this 100 objects at once in the application we have to fetch it in chunks and to fetch it in chunks we have this underscore limit parameter that we can pass to this posts route and the limit can be anything so if i pass the limit 15 then it is only going to fetch us the first 15 objects and we will show this 15 objects in a list in the application and when the list is scrolled to the bottom then we will fetch the next 15 results so how are we going to fetch the next 15 results if we put the limit to 30 then what will this do is it will give us the first 30 results but we don't want this since we have already received the first 15 objects we don't want to fetch them again otherwise it will require internet connection and the whole point of pagination will be pointless if we are fetching everything together so instead of fetching all of this 30 at once how can we fetch the next 15 that is from 16 to 30 and for that we can pass here underscore page parameter and if i pass page as 1 then it will return the first 30 object since the limit is 30 and if i pass 2 then it will fetch me the next 30 results so if i run this then i should get the json array from 31 to 60 and that does happen and then if i change the page to 3 then it will be 61 to 90 and if i set it to 4 then that will give me 91 to 100 so this is how we will be fetching our data in chunks in the application if this is clear then open up command prompt and create the project run flutter create pagination app or anything that you want to name it [Music] and now open the project in vs code if you are on windows then you can run the command code space the name of your project and that will automatically open it in vs code go to the pub spec.yaml file and here we will be adding the flutterblock and http library but i'll do it in a better way go to this extensions section and install this pub spec assist extension this makes adding dependencies in pubspic yaml file very simple so if you have it installed then go to the yaml file and here press ctrl shift p search for add slash update dependencies and type in the name of the package that you want to add and that will automatically add the package with the correct version number and now add the splutter block dependency and save the project that will install the dependency in the lib folder go to main dot dot and here delete everything import the material dot dot create the main function run app and the name of our app is going to be pagination app let's create this stateless widget and we are going to return a material app from here the home of this material app will be the post screen that will be displaying all the posts fetched from the internet and i'm going to create that widget in a separate file so inside the lib create a folder name presentation and inside the presentation create the dart file i'm going to name it posts underscore screen dot dot here import the material.dart and create a stateless widget posts view this widget will return a scaffold it will also have an app bar and the app bar will have a title that will say posts and now go to main.dart provide the posts view to this home before we write any more code let's first create the qubits the repositories the services models and everything that we are going to need on the lib folder right click and if you have installed the block extension then you will see this new qubit button and if you do not know what block is and what the block pattern is in flutter then do check out my other video i have explained the block pattern completely with an example it's a very long video so if you do not know what the block pattern is then you can watch that the name that i'm going to give to my qubit here is posts and that should create the posts cubit in this new qubit folder automatically we will come to this post state and post qubit in some time but let's first create the repository the service and the model i'm going to store all of that in a separate folder and that will be data inside the data create another folder that should hold all the repositories but in this application we are only going to have a single repository that i'll name posts underscore repository dot dot in here create a class named posts repository we will come to the implementation of this posts repository in some time too create another folder for the services that the app is going to have and inside this create a dart file named posts underscore service dot dot and then we will need a model that will convert the json into a dart object and that will be stored in a separate folder as well which will be named models inside this create a file named post dot dot create a class named post this class is going to contain a few members and what are they going to be open the jsonplaceholder.com slash posts and every object here has these four values to it but we are only going to work with the id the title and the body so create variables that will store these values in this class a final string named title one will be body and another one will be an integer [Music] named id we will not have a constructor to create objects of this class instead we will directly create objects from the json that we'll be getting from the internet so create this post dot from json that will take a map object named json here and the title will be equals to jason the key is title the body will also be retrieved from the json with the key body and then the id the key names must match what we have in these objects in this array i think in the post service i did not create the class that will make the network requests so create a class named posts service in this postservice.file and just leave it like this now i am going to provide this posts cubit to the posts view here and to do that we will have to go to the main dot dot and here just wrap this posts view with a block provider and in the create function return an object of the posts cubit block provider is undefined for the type pagination app oh why is okay i think we'll have to import this yes now go to the posts underscore state dot dot and here we will create all the states that our posts qubit will be able to emit so by default the state is going to be posts initial and we are going to have a states named posts loaded this state will be emitted every time we fetch an array of data from the jsontypecode.com make the state extend the abstract state that is post state this state will also contain a list of posts that we will fetch from the internet and our ui will observe this state and show this list of posts on the ui i'm going to name this posts press ctrl dot and import this model and then press ctrl dot on the variable name create the constructor and i'm going to have another state named posts loading this state will be emitted when we are fetching the data from the internet here as well create a list of post and i'm going to name this old posts this old posts will hold the data that is already fetched for example when the app launches we are going to fetch the posts data from the internet and then we will show that in a list and when that list is scrolled to the bottom then we are going to fetch another list but if we are emitting a new state then we will lose the previous state and then our entire data will get lost so to prevent that from happening we are going to extract the data that the state is holding before emitting this post loading state and then we will pass this posts to this old posts and while we are fetching the data from the internet we will show the old posts in our list this will of course make a lot more sense once you do it with me so just hold on and i'm going to have another variable this one will be a boolean i'm going to name this is first fetch when the application launches we will fetch the list of data from the internet and while the data is being fetched this posts loading will be emitted and if this is the first fetch variable is set to true then we are going to show a circular progress indicator at the bottom of the screen but once we have the first set of data and that data is crawled to the bottom and then we are making our next request in that case this is first fetch will not be true and we will show our circular progress indicator at the bottom of the screen now press ctrl dot and create constructor for these funnel fields and i'm going to surround this is first fetch with curly braces and by default it will be set to false it will be set to true only when we are making our first request to the network and this is all of the states that we are going to need for this application now go to the posts underscore qubit here i am going to create an integer variable named page and that will be initialized with value 1. we are going to use this variable to fetch the correct set of data from the json type code server as i already showed how it is going to work at the start of the video if we set page as 1 and let's say limit as 15 then it will get us the first 15 results and then after we have received the first 15 results we will change the page to 2 and then when we make our next request with the limit 15 then we will get the next 15 results that will be from 16 to 30. and in the same way when the page is 3 then it is going to get us the next 15 results and that will happen until we reach the end of the resource and other than this we also need an object of the repository because our qubit will not be making any network request it will ask the repository for the data so create an object of the posts repository press ctrl dot on the constructor and add the final field there in this qubit i'm going to create a function named load posts that will fetch the data and here the first thing i want to do is check if the state is already post's loading if the state is posts loading then we will return from this function otherwise we will emit the state posts loading now here we have to pass the posts that are already being displayed on the screen so that when this new state is emitted we don't lose what we have on the screen but how are we going to get the data that our posts loaded state is holding we can access the current state of a qubit with this state variable so create a variable named current state that will refer to the state of the qubit and now i am going to check if the current state is posts loaded and above this condition create another variable named old posts and that will be initialized with an empty list of type post but if our state is posts loaded then this old post will refer to the post that was already being displayed on the screen and now we can pass this old post to this post loading state it also has this is first fetch boolean and if our page is equal to equals to 1 then it means that we are fetching the data for the first time because after the data has been fetched this page will increment to 2. and after emitting this post's loading state we can ask the repository for the posts so on the repository i am going to call the fetch posts function that we haven't created yet this function will require the page press ctrl dot and create this method now go to the repository the repository will also not be making the network request it is only going to model it so it will require an instance of the post service press ctrl dot and create the constructor this is going to be an async function and the return type of this function will be a list of post it will be a future list of post because we are fetching it from the internet and if you do not know what this future is then just watch a small video on youtube and that will explain that and now we will ask the service to get us the posts data from the internet so here as well i'm going to create a function named fetch posts and it will also require the page parameter here i am going to create a static const variable named fetch limit this is the number of resource that we have to fetch at once and i am going to set it to 15 and along with this i am going to create another variable named base url which is going to hold the url from where we want to fetch the data and the url is jsonplaceholder.typeecode.com posts so copy this and paste it here we will also require to ask the https here and remember to put https and not http because by default http is disabled by android and ios since it is insecure there is a way to allow insecure http but i don't want to get into that in this video so just put https here this function will also be an async function and i'm going to make the network request in a try catch inside the try block create a variable name response and we are going to make a get request to get the data this get function is available in the http package that we installed at the start of the video and here we have to pass uri.parse the sparse function will require the link which is base url and along with this we also want to pass the limit and the page parameters so limit is going to be fetch limit we don't need this curly braces and along with the limit we also require the page now this is going to return a future response so i'm going to put the await keyword to get the real response this response has response dot body which is our data in json string so we will have to convert that json string to json object and we can do that with this json decode function that is there in dart [Music] response dot body the data that we will be getting will be a list so i'm going to cast this json d code to a list dynamic and we are going to return this list dynamic from this method and now make the return type of this fetch post from void to future list dynamic and if any error occurs then we are just going to return an empty list now go to the post repository we are going to store the return value of this function in this posts parameter and also add the await keyword since that's an async function and it is going to return a future we have to convert this list dynamic to this list of post and then we have to return it from the function so posts dot map and this e is nothing but a json object that can be converted to a post object with this post dot from json object creator and here pass the json which is the element and now we are going to cast this to a list and then we will return it from this function that's it from here now go to the post qubit and this value is going to be nothing but the list of posts i am going to rename this value to new posts and once we have a new set of data we are going to increase the page value so when the load posts function is called for the next time we get the next set of results and now we can emit the posts loaded state with the new data that we have fetched but if i pass this new posts here then it will only show the new data that we have fetched and not what we already had since this post variable is not going to hold that data that data is stored in the posts loading state so we are going to get the old data from this post loading state and then we will add this new data to that old post data and then we will emit that piece of data so create a variable named posts and cast the state to posts loading the state is going to be post loading because that is what we have emitted here it cannot be anything else and it has our old post and now we can add the new data that we have fetched to this posts variable and then we can emit this posts out now go to the main dot dot and here we have to provide the post repository to this post qubit so i'm going to make this pagination app dependent on the posts repository press ctrl dot and create this constructor and now from this run app we are going to provide the repository to the pagination app so create an object of the posts repository and this posts repository requires an object of the post service so inside the parentheses create an object of the posts service and now we are going to go to the posts underscore screen dot dot and here we will write the code that will display all that data that we have fetched from the internet to get the first set of data we have to make a call to the load post function that we have in the qubit and i'm going to make a call to that in this build function and to do that i will require a reference to the post qubit that we have passed to this posts view in the main dot dart oh i did not pass the repository here so let me do that so in the post screen we can get the access to that qubit with this block provider of context function and here we have to pass the name of the qubit that we want to get a reference to here it is posts qubit and we can get our first set of data by making a call to the load post function let me also start the emulator so that we can see what we are doing the scaffolds body will be the post list which i will get from a separate function and i'm going to name it post list create that function this will return a block builder widget so with the block builder we will be observing the states of the post qubit and based on the states we will display different stuff on the ui so return a block builder the name of the qubit is post qubit and the state now create the builder function which is going to have the context and the state and now here the first thing that i want to check if the state is post loading and if it is post loading then is it the first fetch if it is the first fetch then we are only going to show a circular progress indicator so i'm going to return a loading indicator here create that function and make it return a circular progress indicator this indicator will be in the center so wrap it with center and i'm also going to give it a padding since the same indicator is going to be used at the bottom of the screen so i want to have it some padding from the rest of the list so wrap it up with a padding and if the state is post loaded or if the state is posts loading but it is not the first fetch then we will get the list of data that we have to show on the ui so i'm going to create a list of post import this model and initialize this with an empty list this posts will refer to the posts that we have in the post loaded state it will refer to this list if the state is post loaded and it will refer to the old post list if the state is post loading so in the posts screen dot dot here check if the state is posts loading if it is posts loading if it is post loading then the posts will refer to the old posts and if it is post loaded then it will refer to the posts right now we have this error because we are not returning anything so that is all right and now we are going to return a list view that will display all of our posts it is going to be a separated list view since i want to add a divider between every list item the item count will be the number of items that we have in our list so posts dot length and this separator builder function let's implement that first parameter is context and second is index but it does not matter what it is we are just going to return a divider from here and the color of the divider will be colors dot gray 400 and now let's implement this item builder this function has the context and the second parameter is the index and now with this index we can get the correct value from this post list and for that post object we can create the ui i am going to create the post item in a separate function named post and the first parameter here is going to be the post object and the second will be the context we will need the context in that function press ctrl dot and create this method this method will return a container and the width of this container will match the width of the screen i am also going to give this container a margin of 10 the child will be a column and the first child of this column will be at text and the text will be the id of the post and the post title let me also add a dot over here so look a little better this text will be stylized a little bit so add the style property [Music] the font size will be 18 color will be black and the font weight will be bold and then i want to add a sized box of height 10. and below this we are going to have another text that will be the body of the post and this will have no style and we can see our post data over here if you are not able to get this result then maybe try hot reloading and if that also does not work then maybe you have messed up in getting the data from the internet so just make a few print statements and check if you are actually getting the data but if you have the same results then let's go ahead i don't want this title to be aligned in center so to make it left aligned i can make the cross axis alignment of this column to start now if i scroll to the bottom then nothing happens we are not getting the next set of results we can implement that with a scroll controller we can pass a scroll controller to this list view and with the scroll controller we can find out if the list has been scrolled to the bottom [Music] so here at the top create an object of scroll controller i'm gonna name this object scroll controller and we will have to pass this scroll controller to the list view and now we can write the code that will detect if the list has been scrolled to the bottom and i will do that in a separate function so let me first create the function and then i will show you where to make a call to that function so create a function named setup scroll controller and inside this we are going to add a listener on the scroll controller so if anything changes in the list view then this function in this addlistener will be called and through this function we can detect the state of the list view so here the first thing that i want to check if this crawl controller dot position is at h so if the list view is at the bottom or if it is at the top then only this condition will be true otherwise it is going to be false and now inside this i have to check if the list view is at the bottom because i don't want to fetch any data if it is at the top and to do that i can check the condition if the scroll controller dot position dot pixels is not equals to zero this pixels will be zero only if the list view is at the top and if it is not at the top then it is going to be at the bottom we are sure about that because this is what that condition is for this is checking if it is at the top or at the bottom and this one is checking if it is not at the top and if it is not at the top then it is at the bottom so if these two conditions are true then we are going to make a call to the load post function and this setup controller is also going to require the context now make a call to this function from this build method by the way if you have a stateful widget then don't add these things over here it should go in the init state that the stateful widgets have otherwise very bad things will happen now let me restart the app and now if i scroll to the bottom the next set of results are already there now what is missing from here well we have to show a circular progress indicator when it is fetching the next set of results so how are we going to add another item to this list to show the loading indicator well for that what i'm going to do is i am going to increase this item count by 1 if the state is loading and in that extra item i am going to show my loading indicator so here create a variable named is loading and it will be set to false by default but it will change to true when the state is loading and now in this item count i am going to check if it is loading and if it is loading then i am going to add 1 otherwise i am going to add 0 and doing this will add that extra element that we will require to show the loading indicator now inside this item builder function i am going to check if the index is lesser than posts.length if it is lesser than posts.length then i am going to show the post and if it is greater than that then i am going to show the loading indicator i think this should make sense when the state is not posts loading then this index will never be equal to or greater than this post dot length and this loading indicator will not be called but if it is loading then this index will be equal to the post dot length since we have added this extra one over here and in that case if we return a loading indicator then the loading indicator will be displayed at the bottom of the screen let me hot reload it and let's see if it is working yes it is working but we have an issue the issue is that when we scroll at the bottom then the loading indicator is not visible unless we scroll it a little bit more so here what we have to do is we have to push the list view to the bottom after rendering this loading indicator so we don't have to manually scroll it to see it and to do that we have this jump to function in our scroll controller and with this we can pass the pixel at which we want to jump our list view to here we have to jump to the bottom and to do that we have this crawlcontroller.position.max scrollextent this max scroll extent will be equal to the height of the list view the entire height but the entire height is not going to contain the loading indicator since it has not been rendered it is rendered after we return the loading indicator what we can do here is we can provide a little bit of delay before jumping to the end of the list so that the loading indicator is added to the list view and this max scroll extent includes this loading indicator so i'm going to add a timer with a duration of maybe 30 milliseconds i think that should be enough let me also import this timer and inside this function i'm going to make a call to this jump to function let me save and hot reload it and let's see if it is working now yes the loading indicator is automatically visible okay so i guess this is it if you have any doubts then put it in the comments i will answer them
Info
Channel: heyletscode
Views: 15,987
Rating: undefined out of 5
Keywords: pagination in flutter, flutter pagination, pagination with bloc, pagination with bloc in flutter, pagination in flutter with bloc pattern, pagination in flutter with cubit, pagination with bloc pattern in flutter, Learn How To Implement Pagination with Flutter, 21:00 NOW PLAYING Flutter Infinite ListView Pagination #1 (/w the BLoC Pattern), 9:47 NOW PLAYING Flutter: Lazy Loading ListViews | Load More Data On Scroll
Id: PCDRFz9jhLc
Channel Id: undefined
Length: 34min 13sec (2053 seconds)
Published: Mon Apr 19 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.