infinite_grouped_list 1.5.0
infinite_grouped_list: ^1.5.0 copied to clipboard
Dynamic scrolling list in Flutter, efficiently grouping items and seamlessly loading more data as user scrolls
1.5.0 #
Added #
- Added
itemKeyBuilderto all four constructors. When provided, each item row is keyed and the sliver delegates usefindChildIndexCallback, so inserting or removing items preserves the element (and itsState) of the remaining items instead of shifting it onto their neighbours — animations, text controllers, and scroll positions inside tiles survive list mutations. Keys must be unique among the currently loaded items. - Added
==,hashCode,toString, andcopyWithtoPaginationInfo.
Changed #
- Error-related parameters and fields (
initialItemsErrorWidget,loadMoreItemsErrorWidget, the reactiveerror, and reactiveerrorWidget) are now typedObject?instead ofdynamic. Existing call sites remain source-compatible.
Fixed #
- Reactive mode (
.reactive()/.reactiveGrid()) now re-groups items immediately whengroupBy,groupCreator,sortGroupBy, orgroupSortOrderchange, matching imperative-mode behaviour. Previously the list kept rendering with the old grouping until the next external data update arrived.
Docs #
- Documented that anchoring identifies groups by their
GroupTitlevalue, soGroupTitleshould implement==andhashCodeconsistently forjumpToGroupto resolve reliably. - Documented that with paging enabled and loaded content shorter than the viewport, additional pages are fetched automatically as the user scrolls until the viewport fills.
1.4.3 #
Fixed #
- Default empty-state, initial-error, and load-more-error texts now follow the
active
Themeinstead of hardcodingColors.black, which rendered them barely visible on dark themes. The empty text usescolorScheme.onSurfaceand both error texts usecolorScheme.error. Custom widgets and error builders are unaffected. - Sorting items within a group is now stable. Dart's
List.sortis not a stable sort, so items whose sort keys compared equal could silently reorder whenever their group was re-sorted as new pages were merged in. Equal-keyed items now deterministically keep the order in which they arrived, across pagination, refreshes, re-groups, and item removals. - An internally owned
ScrollControlleris now disposed after the current frame ends. Swapping from an internal controller to an external one no longer risks the childScrollabletouching a disposed controller while it releases its scroll position.
Changed #
- Removed unused internal pagination helper methods. No public API impact.
Docs #
- Removed a stale
[padding]reference from the constructor documentation; that parameter was removed in an earlier release. - The controller documentation now lists all of its capabilities (
getItems,loadItems,refresh,addItems,remove,removeWhere,jumpToGroup) instead of only the original three. - Fixed typos in doc comments ("seperator" → "separator", "grpup" → "group").
Testing #
- Added regression tests for dark-theme default text colors, sort stability
with equal keys (unit-level through
GroupManagerand widget-level across paginated loads), and internal-to-external scroll controller swap lifecycle.
1.4.2 #
Fixed #
- Separators from
separatorBuilderare no longer drawn after the last item of each group. Previously a trailing separator appeared beneath the final item of every group (just above the next header); separators now appear only between items, matching the documented intent andListView.separatedsemantics. This applies to both list and grid layouts. If you relied on the trailing separator, add the spacing via the group header or item padding instead.
Previous vs current behaviour:

refresh()(pull-to-refresh andcontroller.refresh()) is no longer silently skipped when a scroll-triggered load-more is still in flight. The refresh now waits for the pending load to settle and then resets pagination and re-fetches the first page.
Docs #
- Clarified that
sortGroupBy/groupSortOrdersort items within each group, while the order of the groups themselves follows the order in which each group is first encountered in the loaded data. - Documented that grouping callbacks (
groupBy,groupCreator,sortGroupBy) should be stable references to avoid unnecessary re-grouping on parent rebuilds.
1.4.1 #
Fixed #
- List items now stretch to the full cross-axis width. Previously, items were centered with intrinsic width. Wrap items in
Centerif you relied on the old behavior.
1.4.0 #
Added #
- Expanded package-level test coverage across pagination, refresh, reactive loading, anchoring, helper classes, and empty/error states.
- Added
maxRetriestojumpToGroup(loadUntilFound: true)so callers can cap extra page loads explicitly.
Changed #
- Moved tooling packages out of runtime dependencies.
Fixed #
- Fixed controller rebinding and external
ScrollControllerownership so parent-managed controllers are no longer disposed by the widget. - Prevented duplicate reactive
onLoadMoreTriggereddispatches while a reactive load is already pending. - Stopped
jumpToGroup(loadUntilFound: true)from retrying forever after load failures.- There is also optional
maxRetriesparameter to cap the extra page loads defaulting to3.
- There is also optional
Breaking Changes #
- Removed the misspelled
seperatorBuilderAPI. UseseparatorBuilder.
1.3.1 #
Added #
- Added optional
enableAnchoringplusInfiniteGroupedListController.jumpToGroupso apps can programmatically snap to any group header, such as "Today".
Fixed #
- Replaced an invalid
Spacerusage in the example app'sListView, eliminating theParentDataWidgetassertion and keeping the showcase aligned with the package API.
1.3.0 #
Added #
- Added
InfiniteGroupedList.reactive()for reactive state management patterns. - Added
InfiniteGroupedList.reactiveGrid()for grid layouts with reactive patterns. - Added external state support through
items,isLoading,hasReachedMax, anderror. - Added a comprehensive reactive BLoC example with mock API, error handling, and loading states.
Changed #
- Improved controller behavior so it adapts automatically to reactive versus imperative mode.
- Added safety guards so controller mutation methods throw helpful errors in reactive mode.
- Improved lifecycle handling so reactive widgets update when external state changes through
didUpdateWidget. - Optimized reactive data handling to avoid unnecessary rebuilds.
- Expanded the example app with richer navigation, more polished UI, and clearer pattern comparison.
- Improved the documentation with more complete usage guidance and architectural examples.
Breaking Changes #
- None.
1.2.10 #
Added #
- Added
scrollControllerto all constructors so callers can provide their own scroll controller.
1.2.9 #
Added #
- Added helper methods for group management:
_sortSingleGroup,_addItemsToGroups, and_createInitialGroups.
Changed #
- Optimized group operations with targeted updates instead of full regrouping.
- Reduced memory usage by avoiding unnecessary data structure recreation.
- Implemented more efficient item addition with selective group updates.
- Optimized item removal with targeted group processing.
- Improved refresh operation efficiency.
Fixed #
- Fixed potential memory leaks by properly clearing controller callbacks.
- Improved scroll performance for large datasets.
- Improved handling of empty groups after item removal.
1.2.7 #
1.2.6 #
Added #
- Added
limittoInfiniteGroupedListControllerto define the expected page size from remote calls. - Added
onNoMoreItemsFound, which is triggered when the response contains fewer items than the configuredlimit.
1.2.0 #
Added #
- Added the
physicsparameter. It defaults toAlwaysScrollablePhysics.
Changed #
- Tweaked
initialItemsErrorWidgetandloadMoreItemsErrorWidget. They now accept the error and return aWidget.
initialItemsErrorWidget: (error) => GestureDetector(
child: Text(
error.toString(),
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
decoration: TextDecoration.underline,
decorationColor: Colors.blue,
color: Colors.blue,
),
),
),
loadMoreItemsErrorWidget: (error) => GestureDetector(
child: Text(
error.toString(),
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
decoration: TextDecoration.underline,
decorationColor: Colors.blue,
color: Colors.blue,
),
),
),
Breaking Changes #
initialItemsErrorWidgetandloadMoreItemsErrorWidgetnow receive the error and must return a widget.
