EntityPagination<O extends Object> class

A lazily loaded, paginated view over a select operation.

It keeps the pages it has already loaded and never fetches implicitly: the synchronous accessors (operator [], loadedEntities) only ever see what is loaded, and only the FutureOr methods (getAt, getPage, loadNextPage, loadAll, stream) fetch.

Pages are 1-based (matching the page parameter of the select* methods) and entry indexes are 0-based (matching a Dart List): see indexOfPage and pageOfIndex.

Pages can be loaded out of order, leaving gaps: getAt(45) with a limit of 20 loads only page 3, so loadedPages is [3] while indexes 0..39 stay unloaded.

The total length is not known upfront

A paginated select doesn't count the matching entries, so totalLength is null until the final page is identified. Since every page except the last one holds exactly limit entries, identifying the final page is enough to compute the total — even when there are gaps:

totalLength == (finalPage - 1) * limit + <entries of finalPage>

See isFinalPageResolved for when that happens.

Not a List

This is deliberately not a List or an Iterable: both require a length, which is exactly what a paginated select can't answer until it reaches the end. Use operator [] for what is loaded, and loadAll when a full list is really needed.

Consistency

Each page is an independent select, without a shared Transaction. Entries inserted or deleted between two page loads shift the offsets, so a page loaded later can repeat or skip entries. This is inherent to offset-based pagination; ordering by ID (the default of the paginate* methods) makes it as stable as it can be.

Constructors

EntityPagination({required int limit, required EntityPageLoader<O> pageLoader, String? query, EntityPaginationListener<O>? onEvent})

Properties

finalPage → int?
The final page, or null while unresolved. See isFinalPageResolved.
no setter
hashCode → int
The hash code for this object.
no setterinherited
isFinalPageResolved → bool
Whether the final page has been identified.
no setter
isKnownEmpty → bool
Whether the select is known to match no entry at all.
no setter
limit → int
The page size: the maximum number of entries of a page.
final
loadedEntities → List<O>
The loaded entries, in index order. Gaps are skipped.
no setter
loadedEntitiesLength → int
The number of loaded entries. Entries in a gap are not counted, so this can be less than maxLoadedIndex + 1.
no setter
loadedPages → List<int>
The loaded page numbers, ascending. Can have gaps.
no setter
loadedPagesLength → int
The number of loaded pages.
no setter
maxKnownPage → int?
The highest page known to exist: the highest loaded page that came back with entries. null if no page with entries was loaded yet.
no setter
maxLoadedIndex → int?
The highest entry index that is loaded, or null if none is.
no setter
maxLoadedPage → int?
The highest loaded page, or null if nothing was loaded yet.
no setter
onEvent ↔ EntityPaginationListener<O>?
An optional hook notified of what is being fetched, or null (the default) to notify nothing. See EntityPaginationEvent.
getter/setter pair
pageLoader → EntityPageLoader<O>
Loads a page. See EntityPageLoader.
final
query → String?
An optional description of the paginated query, for toString.
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
totalLength → int?
The total number of entries, or null while isFinalPageResolved is false.
no setter

Methods

getAt(int index) → FutureOr<O?>
The entry at index, loading its page if needed. Returns null if index is out of range.
getPage(int page) → FutureOr<List<O>>
The entries of page, loading it if needed.
getRange(int startIndex, int endIndex) → FutureOr<List<O>>
The entries from startIndex (inclusive) to endIndex (exclusive), loading every page spanning the range, including pages inside a gap.
indexOfPage(int page) → int
The index of the 1st entry of page.
information({bool extended = false}) → Map<String, dynamic>
isIndexKnownOutOfRange(int index) → bool
Whether index is known to be out of range.
isIndexLoaded(int index) → bool
Returns true if the entry at index is loaded.
isPageLoaded(int page) → bool
Returns true if page was already loaded (even if it came back empty).
loadAll({int? maxPages}) → FutureOr<int?>
Loads every page from page 1 until the end, so that afterwards loadedEntities holds the complete result with no gap.
loadedPageEntities(int page) → List<O>?
The loaded entries of page, or null if it is not loaded.
loadNextPage() → FutureOr<List<O>?>
Loads the page after maxLoadedPage (or page 1 when nothing is loaded).
loadPage(int page) → FutureOr<List<O>>
Loads page (1-based), or returns it if already loaded.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
pageOfIndex(int index) → int
The page holding the entry at index.
refresh() → FutureOr<void>
Re-fetches the currently loaded pages, discarding what was known about the end (it may have moved).
reset() → void
Discards every loaded page and everything known about the end, keeping the query.
stream({int fromPage = 1}) → Stream<O>
Streams the entries from fromPage, loading the pages as it goes.
toString() → String
A string representation of this object.
override

Operators

operator ==(Object other) → bool
The equality operator.
inherited
operator [](int index) → O?
The loaded entry at index, or null if it is not loaded (in a gap, in a page not loaded yet, or out of range).