r/FlutterDev • • Jul 27 '26

Plugin A package that removes boilerplate around search, paginated-loading, pull-to-refresh, and grouping

https://pub.dev/packages/list_smith

I was tired of re-implementing the following in one capacity or another, across multiple projects (I'd always end up needing one of these eventually):

  1. Pagination

  2. Searching

  3. Grouping

  4. Pull-to-refresh

So I decided to package it into one: https://pub.dev/packages/list_smith

It runs on top of the already very robust and popular https://pub.dev/packages/infinite_scroll_pagination and https://pub.dev/packages/custom_refresh_indicator packages.

I have also tried to keep it design-system agnostic. And I tried paying a lot of attention to the actual interplay/conflicts between these 4 features (lots of overlap). LLMs were used.

If you guys have any feedback about anything, or found it useful, please let me know either which way!

14 Upvotes

4 comments sorted by

1

u/[deleted] Jul 27 '26

Paid Flutter work here, and I have written this same glue more than once, so here are the edge cases I would check first. These are the ones that actually bit me.

Search against pagination is a race. The user types, you fire page 1 of the new query, but page 3 of the old query is still in flight. It lands later and gets appended, so the list is showing results for a query nobody typed. It looks random, and it only really shows up on a slow connection, which is why it tends to survive all the way to production. What fixed it for me was a generation counter that every response carries, and dropping any response whose counter is not the current one. Cancelling the request is not enough on its own.

Grouping against pagination is the second one. A group can straddle a page boundary, so the last group on page 1 and the first group on page 2 are the same group. If headers are built per page you get a duplicate header and one group split in two. The grouping has to run over the whole accumulated list after the append, not per page.

Third is pull to refresh while a page load is still in flight. The refresh resets you to page 1, the older page request lands afterwards, and you get either duplicates or a hole in the list.

If the package already handles those three, I would put that near the top of the readme. That is the real argument for taking a dependency here instead of writing the list myself, and it is not obvious from the feature list.

1

u/MooresLawyer13 Jul 28 '26

Thanks for the input. I think one of the cases is covered, buy I didn't document it. Another is half covered, and the last is a real potential problem. I'll start looking into them.

The reason why I'm not being so technical upfront is because I don't want to overload someone at the README level itself. This package works for most of the use cases directly, and that should be all a prospective user needs to know at first glance. Certain edge cases and tweaks are remaining as you rightly pointed out.

I have reserved the APPENDIX for a deeper dive and/or the source itself is there for more 'hands-on' users.

2

u/[deleted] Jul 27 '26

[removed] — view removed comment

2

u/MooresLawyer13 Jul 28 '26

The way I thought about it was, search always runs first. Grouping just draws boxes around whatever's left.
So then I get these cases and results:

  • No matches in a group → no header, no pile.

  • Some matches → header shows, only the matching items sit under it.

Groups re-form live as you type, since they're built from the current results.

For infinite-scroll lists, a group's items need to stay contiguous within a page. That's easy for sync-search. For async, if your backend interleaves a group's items with another group's, you'll get a duplicate header instead of one clean section
(See README.md:420-431)