Skip to main content

Work and Progress

Every FdcDataSet owns a lightweight observable work model through dataSet.work.

It reports dataset operations such as opening, filtering, sorting, searching, applying updates, explicit loading, and application-defined work.

final work = dataSet.work;

if (work.isWorking) {
debugPrint('${work.phase}: ${work.message}');
}

Work phases

FdcDataSetWorkPhase describes the coarse operation currently running:

PhaseMeaning
idleNo reported work is active
openOpening or reloading rows
filterFiltering or rebuilding the filtered view
sortSorting or rebuilding sorted order
searchGlobal search query or local search rebuild
applyUpdatesApplying pending changes through the adapter
loadExplicit row loading or aggregate-style data work
customApplication-defined dataset work

The enum is intentionally small. It identifies the user-relevant type of work without turning the dataset into a general task framework.

Determinate and indeterminate work

switch (dataSet.work.mode) {
case FdcDataSetWorkMode.determinate:
final progress = dataSet.work.progress ?? 0.0;
break;
case FdcDataSetWorkMode.indeterminate:
// Show an indeterminate indicator.
break;
case null:
// Idle.
break;
}

For determinate work, progress is normalized to 0.0..1.0.

For indeterminate work, progress is null.

Listen for lifecycle transitions

FdcDataSetWork is a ChangeNotifier:

void handleWorkTransition() {
final work = dataSet.work;

if (work.isWorking) {
debugPrint('Started ${work.phase}: ${work.message}');
} else if (work.error != null) {
debugPrint('Work failed: ${work.error}');
} else {
debugPrint('Work completed');
}
}

dataSet.work.addListener(handleWorkTransition);

Notifications are emitted when work starts, completes, or fails.

Progress updates are intentionally silent

Granular progress updates do not call notifyListeners().

This is deliberate: a large operation may update progress many times, and broadcasting every increment through the widget tree would create a notification storm.

UI that needs continuously updated percentage progress should poll dataSet.work.progress while isWorking is true. Lifecycle listeners are still useful for starting and stopping that polling loop.

Conceptually:

work starts
→ listener notified
→ UI begins lightweight polling
→ progress changes silently
→ work completes or fails
→ listener notified
→ UI stops polling

Current work snapshot

While work is active, dataSet.work.current exposes an immutable FdcDataSetWorkInfo snapshot:

final current = dataSet.work.current;

if (current != null) {
debugPrint('Work id: ${current.id}');
debugPrint('Started: ${current.startedAt}');
debugPrint('Phase: ${current.phase}');
debugPrint('Mode: ${current.mode}');
}

Each work operation receives a dataset-local monotonic id.

The snapshot contains:

  • id,
  • phase,
  • mode,
  • startedAt,
  • optional message,
  • error and stack trace on failed lifecycle snapshots.

Failure state

After a failed operation:

final error = dataSet.work.error;
final stackTrace = dataSet.work.stackTrace;

These properties retain the most recently captured work failure until a new work operation begins.

Adapter and dataset errors still flow through the normal FDC error pipeline; the work model provides operation-state observability rather than replacing error handling.

See Error Handling.

Lifecycle callbacks

Dataset lifecycle callbacks provide another way to react to work transitions:

FdcDataSet(
fields: fields,
onWorkStarted: (dataSet, info) {
// Operation started.
},
onWorkCompleted: (dataSet, info) {
// Operation completed.
},
onWorkError: (dataSet, info) {
// Operation failed.
},
)

Use callbacks for dataset/business orchestration. Use dataSet.work when a UI or observer needs current state.

See Lifecycle Callbacks.

Grid progress UI

The grid can visualize dataset work through its progress components. The important architectural rule is that the DataSet owns work state; the grid only renders it.

This keeps long-running operation state reusable outside the grid and avoids coupling data execution strategy to one widget.