TaskProgress class
Progress update during task execution.
Workers can report progress during long-running operations. Listen to NativeWorkManager.progress to receive real-time updates and show progress bars or status messages in your UI.
Reporting Progress from Worker
@pragma('vm:entry-point')
Future<WorkerResult> downloadFiles(WorkerInput input) async {
final urls = input.data['urls'] as List<String>;
final total = urls.length;
for (var i = 0; i < urls.length; i++) {
// Report progress
await input.reportProgress(
progress: ((i + 1) / total * 100).round(),
message: 'Downloading file ${i + 1} of $total',
currentStep: i + 1,
totalSteps: total,
);
await downloadFile(urls[i]);
}
return WorkerResult.success();
}
Listening to Progress Updates
void initState() {
super.initState();
// Listen to progress for all tasks
NativeWorkManager.progress.listen((progress) {
setState(() {
_currentProgress = progress.progress;
_statusMessage = progress.message ?? 'Processing...';
});
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
LinearProgressIndicator(value: _currentProgress / 100),
Text(_statusMessage),
if (_currentStep != null && _totalSteps != null)
Text('Step $_currentStep of $_totalSteps'),
],
);
}
Filtering Progress by Task
// Only listen to specific task's progress
NativeWorkManager.progress
.where((p) => p.taskId == 'bulk-upload')
.listen((progress) {
print('Upload: ${progress.progress}% - ${progress.message}');
if (progress.currentStep != null && progress.totalSteps != null) {
print('File ${progress.currentStep}/${progress.totalSteps}');
}
});
Multi-Step Task with Progress
@pragma('vm:entry-point')
Future<WorkerResult> processImages(WorkerInput input) async {
final images = input.data['images'] as List<String>;
final steps = ['Download', 'Resize', 'Compress', 'Upload'];
final totalSteps = images.length * steps.length;
var currentStep = 0;
for (var image in images) {
// Download
currentStep++;
await input.reportProgress(
progress: (currentStep / totalSteps * 100).round(),
message: 'Downloading $image',
currentStep: currentStep,
totalSteps: totalSteps,
);
await downloadImage(image);
// Resize
currentStep++;
await input.reportProgress(
progress: (currentStep / totalSteps * 100).round(),
message: 'Resizing $image',
currentStep: currentStep,
totalSteps: totalSteps,
);
await resizeImage(image);
// Compress
currentStep++;
await input.reportProgress(
progress: (currentStep / totalSteps * 100).round(),
message: 'Compressing $image',
currentStep: currentStep,
totalSteps: totalSteps,
);
await compressImage(image);
// Upload
currentStep++;
await input.reportProgress(
progress: (currentStep / totalSteps * 100).round(),
message: 'Uploading $image',
currentStep: currentStep,
totalSteps: totalSteps,
);
await uploadImage(image);
}
return WorkerResult.success();
}
Progress with Network Upload
@pragma('vm:entry-point')
Future<WorkerResult> uploadLargeFile(WorkerInput input) async {
final file = File(input.data['filePath']);
final fileSize = await file.length();
var uploaded = 0;
await uploadWithProgress(
file,
onProgress: (bytes) {
uploaded += bytes;
final progress = (uploaded / fileSize * 100).round();
input.reportProgress(
progress: progress,
message: 'Uploaded ${uploaded ~/ 1024}KB / ${fileSize ~/ 1024}KB',
);
},
);
return WorkerResult.success();
}
Progress Fields
- taskId: Identifier of the task reporting progress
- progress: Percentage (0-100) of completion
- message: Optional human-readable status message
- currentStep: Current step number (for multi-step tasks)
- totalSteps: Total number of steps (for multi-step tasks)
Platform Behavior
Android:
- Progress delivered via WorkManager's setProgress API
- Updates throttled to ~1 per second to conserve resources
- Reliable delivery while app is active
iOS:
- Progress delivered when app is active or backgrounded
- Updates batched if app is suspended
- May be delayed for terminated apps
Important Notes
- Progress updates are best-effort delivery
- Not guaranteed if app is terminated
- Updates may be throttled by the OS
- Don't rely on receiving every single update
- Progress is optional - tasks work without it
Performance Tips
✅ Do report progress at meaningful intervals (e.g., every file, every 5%) ✅ Do include useful messages for users ✅ Do use currentStep/totalSteps for multi-step tasks
❌ Don't report progress on every byte (too frequent) ❌ Don't report progress more than once per second ❌ Don't report progress for tasks under 5 seconds ❌ Don't block worker execution waiting for progress delivery
When to Use Progress
Good for:
- File uploads/downloads (show bytes transferred)
- Batch processing (show items processed)
- Multi-step workflows (show current step)
- Long operations (>10 seconds)
Not needed for:
- Quick tasks (<5 seconds)
- Tasks with no intermediate steps
- Tasks running while app is terminated
See also:
- NativeWorkManager.progress - Stream of progress updates
- NativeWorkManager.reportDartWorkerProgress - Report from DartWorker callback
- TaskEvent - Task completion notification
- Available extensions
- Annotations
Constructors
Properties
- bytesDownloaded → int?
-
Bytes downloaded so far (download workers only).
final
- currentStep → int?
-
Current step number (for multi-step tasks).
final
- hashCode → int
-
The hash code for this object.
no setteroverride
- hasNetworkInfo → bool
-
Whether this progress update carries byte-level information.
no setter
- message → String?
-
Optional status message.
final
- networkSpeed → double?
-
Current download/upload speed in bytes per second.
final
- networkSpeedHuman → String
-
Available on TaskProgress, provided by the TaskProgressExtensions extension
Returns the network speed in a human-readable format (e.g., "1.2 MB/s").no setter - progress → int
-
Progress percentage (0-100).
final
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- taskId → String
-
ID of the task.
final
- timeRemaining → Duration?
-
Estimated time remaining in milliseconds.
final
- timeRemainingHuman → String
-
Available on TaskProgress, provided by the TaskProgressExtensions extension
Returns the estimated time remaining in a human-readable format (e.g., "2m 15s").no setter - totalBytes → int?
-
Total file size in bytes (download workers only).
final
- totalSteps → int?
-
Total number of steps.
final
Methods
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toMap(
) → Map< String, dynamic> - Convert to map.
-
toString(
) → String -
A string representation of this object.
override
Operators
-
operator ==(
Object other) → bool -
The equality operator.
override