I want to use Flutter’s ListView
to display a list of items, and the data of the items are obtained from a RESTful API with pagination support. E.g.
GET /transactions?page=1&limit=10
{
"transactions": [ ... ]
"pagination": {
"total": 100
}
}
I know I can use ListView.builder()
, and let the itemBuilder
callback argument returns a widget wrapped in FutureBuilder
.
However, ListView.builder()
also has a itemCount
argument. I don’t know the total count of items before fetching the first page. Without the itemCount
argument, the itemBuilder
may be called with index
exceeding the total number of items.
One way that comes to my mind is to wrap the ListView
in another FutureBuilder
and asynchronously call the API to get the total count. However, the total count may change over time. For example, the total count can be 100 initially. But when the user scrolls to the end, some items are removed, and the total count becomes 90. When it happens, it’s still possible that itemBuilder
is called with index
out of bound.
What should I do to deal with this situation?
CodePudding user response:
If I understand you well, and from what I can see in the response. you want to do a pagination thing. use infinite_scroll_pagination
CodePudding user response:
This shouldn't be an issue. You should call ListView.builder()
only when you already have the API items properly returned. And if that's the case, you can tell the length of the items (after they have successfully returned), and use this length as the itemCount
of ListView.builder()
.
Any other solution you use (asides ListView.builder()
) will still require the API to return the data successfully before rendering the UI (based on the returned data).
If you understand the above, then your problem should be solved.
But if it still doesn't solve it, use ListView
with children
instead of the .builder
method.
After the API has returned the items, call .map
method on the returned List/Iterable (from the API). This method should return the widgets that your .builder()
would have returned. You are calling this .map
method against children
property of ListView
. Something like:
ListView(
// where items is from the API
children: items.map((i) => Text(i)).toList(),
)
You can choose to use spread operator instead of appending .toList()
. Something like:
ListView(
// where items is from API
children: [...items.map((i) => Text(i))],
)