Flutter: Infinite ListView with Redux
Motivation
If you need to implement an app with more than one screen the odds are that one of the screens will represent its data in some form of a list. I’d like to show you how you can develop an “infinite” list of items with “pull-to-refresh” and “error-handling” on top of Flutter + Redux.
Prerequisites
Make sure you feel comfortable with the terms described in the docs in redux.dart and flutter_redux repositories. I would also suggest that you take a look at my previous article.
Goal
An app that displays issues from the flutter GitHub repository sounds reasonable to me for the sake of this demo.
Here is the result that will be achieved in the end:
Development
We’ll need flutter_redux and http packages, so get them added to your pubspec.yaml file and installed. Also, intl package and redux_logging packages will be useful for date formatting and debugging purposes respectively.
Model
It’s just a simple class for holding some info about a Github issue. It also can initialize itself from a piece of JSON.
State
There is not so much data that we’ll need to keep inside the state: the list of items, the flags indicating whether the data is being loaded and whether there is more data available, and the error.
You may have noticed the toString
method. It can be used for debugging purposes and comes in handy if you decide to use LoggingMiddleware
.
Actions
There are two actions for dealing with actual data and two actions for dealing with a possible error.
Reducers
The reducers that create a new state based on a received action are a bit more complicated than actions, but only a bit. They are just simple pure functions that are combined by the combineReducers
function the library gives us.
Middleware
The implemented middleware basically consists of the function that tries to load data from the API and posts either the successful action or the action indicating a failure.
Container
Now we are getting closer to the presentation layer. Here is the container widget that is responsible for converting the latest App State to a _ViewModel
and connecting the _ViewModel
to the presentation widget.
Presentation
This is the part where things become more interesting. Let’s start with two tiny presentation components that will be utilized in the HomeScreen
. They are CustomProgressIndicator
and GithubIssueListItem
.
Here goes the core presentation logic.
Pay more attention to the HomeScreen
. There are a few things worth noticing:
- The screen involves the
ScrollController
to determine when we need to invoke theloadNextPage
function. - Something called
Debouncer
is used (the implementation you’ll see below). It’s just a tiny class with a timer inside it that ensures that consecutive events from theScrollController
won’t create tons of requests for a next page, but rather the only request will be made in the specified period of time. RefreshIndicator
that helps us significantly to get the so-called “pull-to-refresh” feature.ErrorNotifier
that is responsible for showing a toast notification in case an error occurs. If you need more details on this one, take a look at my previous article.
This is the code for the ErrorNotifer
.
And here is how the ErrorNotifier
looks like in action.
This is the Debouncer
that was mentioned above.
Finally, here is the main.dart
file that combines all the described components.
Don’t hesitate to give this sample a go yourself, grab the sources from the Github repo.