Skip to content

Commit

Permalink
Clarify how retries are handled (fluttercommunity#274)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastian Roth authored Jun 7, 2021
1 parent 9f5d2a8 commit 65dbe1e
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 20 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ void main() {
---

# Work Result

The `Workmanager().executeTask(...` block supports 3 possible outcomes:

1. `Future.value(true)`: The task is successful.
2. `Future.value(false)`: The task did not complete successfully and needs to be retried.
3. `Future.error(...)`: The task failed.

On Android, the `BackoffPolicy` will configure how `WorkManager` is going to retry the task.

Refer to the example app for a successful, retrying and a failed task.

# Customisation (Android only!)
Not every `Android WorkManager` feature is ported.

Expand Down Expand Up @@ -131,6 +143,7 @@ Add some input data for your task. Valid value types are: `int`, `bool`, `double
},
);
```

## BackoffPolicy
Indicates the waiting strategy upon task failure.
The default is `BackoffPolicy.exponential`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package be.tramckrijte.workmanager
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.concurrent.futures.ResolvableFuture
import androidx.work.ListenableWorker
import androidx.work.WorkerParameters
Expand Down Expand Up @@ -30,6 +31,8 @@ class BackgroundWorker(
private lateinit var backgroundChannel: MethodChannel

companion object {
const val TAG = "BackgroundWorker"

const val PAYLOAD_KEY = "be.tramckrijte.workmanager.INPUT_DATA"
const val DART_TASK_KEY = "be.tramckrijte.workmanager.DART_TASK"
const val IS_IN_DEBUG_MODE_KEY = "be.tramckrijte.workmanager.IS_IN_DEBUG_MODE_KEY"
Expand Down Expand Up @@ -131,7 +134,8 @@ class BackgroundWorker(
stopEngine(Result.failure())
}

override fun error(p0: String?, p1: String?, p2: Any?) {
override fun error(errorCode: String?, errorMessage: String?, errorDetails: Any?) {
Log.e(TAG, "errorCode: $errorCode, errorMessage: $errorMessage")
stopEngine(Result.failure())
}

Expand Down
73 changes: 57 additions & 16 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:async';
import 'dart:io';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
Expand All @@ -9,6 +10,8 @@ import 'package:workmanager/workmanager.dart';
void main() => runApp(MyApp());

const simpleTaskKey = "simpleTask";
const rescheduledTaskKey = "rescheduledTask";
const failedTaskKey = "failedTask";
const simpleDelayedTask = "simpleDelayedTask";
const simplePeriodicTask = "simplePeriodicTask";
const simplePeriodic1HourTask = "simplePeriodic1HourTask";
Expand All @@ -22,6 +25,20 @@ void callbackDispatcher() {
prefs.setBool("test", true);
print("Bool from prefs: ${prefs.getBool("test")}");
break;
case rescheduledTaskKey:
final key = inputData!['key']!;
final prefs = await SharedPreferences.getInstance();
if (prefs.containsKey('unique-$key')) {
print('has been running before, task is successful');
return true;
} else {
await prefs.setBool('unique-$key', true);
print('reschedule task');
return false;
}
case failedTaskKey:
print('failed task');
return Future.error('failed');
case simpleDelayedTask:
print("$simpleDelayedTask was executed");
break;
Expand All @@ -34,7 +51,7 @@ void callbackDispatcher() {
case Workmanager.iOSBackgroundTask:
print("The iOS background fetch was triggered");
Directory? tempDir = await getTemporaryDirectory();
String? tempPath = tempDir?.path;
String? tempPath = tempDir.path;
print(
"You can access other plugins in the background, for example Directory.getTemporaryDirectory(): $tempPath");
break;
Expand Down Expand Up @@ -95,21 +112,45 @@ class _MyAppState extends State<MyApp> {
//This task runs once.
//Most likely this will trigger immediately
PlatformEnabledButton(
platform: _Platform.android,
child: Text("Register OneOff Task"),
onPressed: () {
Workmanager().registerOneOffTask(
"1",
simpleTaskKey,
inputData: <String, dynamic>{
'int': 1,
'bool': true,
'double': 1.0,
'string': 'string',
'array': [1, 2, 3],
},
);
}),
platform: _Platform.android,
child: Text("Register OneOff Task"),
onPressed: () {
Workmanager().registerOneOffTask(
"1",
simpleTaskKey,
inputData: <String, dynamic>{
'int': 1,
'bool': true,
'double': 1.0,
'string': 'string',
'array': [1, 2, 3],
},
);
},
),
PlatformEnabledButton(
platform: _Platform.android,
child: Text("Register rescheduled Task"),
onPressed: () {
Workmanager().registerOneOffTask(
"1-rescheduled",
rescheduledTaskKey,
inputData: <String, dynamic>{
'key': Random().nextInt(64000),
},
);
},
),
PlatformEnabledButton(
platform: _Platform.android,
child: Text("Register failed Task"),
onPressed: () {
Workmanager().registerOneOffTask(
"1-failed",
failedTaskKey,
);
},
),
//This task runs once
//This wait at least 10 seconds before running
PlatformEnabledButton(
Expand Down
6 changes: 3 additions & 3 deletions lib/src/workmanager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ typedef BackgroundTaskHandler = Future<bool> Function(
///
/// ```
/// void callbackDispatcher() {
/// Workmanager.executeTask((taskName, inputData) {
/// Workmanager().executeTask((taskName, inputData) {
/// switch(taskName) {
/// case "":
/// print("Replace this print statement with your code that should be executed in the background here");
Expand All @@ -40,7 +40,7 @@ typedef BackgroundTaskHandler = Future<bool> Function(
/// }
///
/// void main() {
/// Workmanager.initialize(callbackDispatcher);
/// Workmanager().initialize(callbackDispatcher);
/// }
/// ```
///
Expand All @@ -66,7 +66,7 @@ class Workmanager {
///
/// ```
/// void callbackDispatcher() {
/// Workmanager.executeTask((taskName, inputData) {
/// Workmanager().executeTask((taskName, inputData) {
/// switch (taskName) {
/// case Workmanager.iOSBackgroundTask:
/// stderr.writeln("The iOS background fetch was triggered");
Expand Down

0 comments on commit 65dbe1e

Please sign in to comment.