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:

Available extensions
Annotations

Constructors

TaskProgress({required String taskId, required int progress, String? message, int? currentStep, int? totalSteps, int? bytesDownloaded, int? totalBytes, double? networkSpeed, Duration? timeRemaining})
const
TaskProgress.fromMap(Map<String, dynamic> map)
Create from platform channel map.
factory

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