Skip to content

Commit 1e2e94b

Browse files
enedclaude
andcommitted
feat: create dedicated Task Customization page
- Move advanced features from quickstart to separate customization page - Keep quickstart focused on basic setup and usage - Add comprehensive customization guide covering: - Input data passing and access - Task constraints (network, battery, storage) - Task tagging and management - Cancellation methods - Error handling and retries - Best practices and resource management - Add to navigation under Reference section - Update quickstart Next Steps to reference customization page 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 76264ce commit 1e2e94b

3 files changed

Lines changed: 288 additions & 60 deletions

File tree

docs.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
"group": "Reference",
2626
"tab": "root",
2727
"pages": [
28+
{
29+
"title": "Task Customization",
30+
"href": "/customization"
31+
},
2832
{
2933
"title": "Debugging",
3034
"href": "/debugging"

docs/customization.mdx

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
---
2+
title: Task Customization
3+
description: Advanced task configuration with constraints, input data, and management
4+
---
5+
6+
Configure background tasks with constraints, input data, and advanced management options.
7+
8+
## Input Data
9+
10+
Pass data to your background tasks and access it in the callback:
11+
12+
```dart
13+
// Schedule task with input data
14+
Workmanager().registerOneOffTask(
15+
"upload-task",
16+
"file_upload",
17+
inputData: {
18+
'fileName': 'document.pdf',
19+
'uploadUrl': 'https://api.example.com/upload',
20+
'retryCount': 3,
21+
'userId': 12345,
22+
},
23+
);
24+
25+
// Access input data in your task
26+
@pragma('vm:entry-point')
27+
void callbackDispatcher() {
28+
Workmanager().executeTask((task, inputData) async {
29+
print('Task: $task');
30+
print('Input: $inputData');
31+
32+
// Extract specific values
33+
String? fileName = inputData?['fileName'];
34+
String? uploadUrl = inputData?['uploadUrl'];
35+
int retryCount = inputData?['retryCount'] ?? 0;
36+
int userId = inputData?['userId'] ?? 0;
37+
38+
// Use the data in your task logic
39+
await uploadFile(fileName, uploadUrl, userId);
40+
41+
return Future.value(true);
42+
});
43+
}
44+
```
45+
46+
<Info>
47+
**Input Data Types:** You can pass basic JSON-serializable types: `String`, `int`, `double`, `bool`, `List`, `Map`. Complex objects need to be serialized first.
48+
</Info>
49+
50+
## Task Constraints
51+
52+
Control when tasks should run based on device conditions:
53+
54+
```dart
55+
Workmanager().registerOneOffTask(
56+
"sync-task",
57+
"data_sync",
58+
constraints: Constraints(
59+
networkType: NetworkType.connected, // Require internet connection
60+
requiresBatteryNotLow: true, // Don't run when battery is low
61+
requiresCharging: false, // Can run when not charging
62+
requiresDeviceIdle: false, // Can run when device is active
63+
requiresStorageNotLow: true, // Don't run when storage is low
64+
),
65+
);
66+
```
67+
68+
### Network Constraints
69+
70+
```dart
71+
// Different network requirements
72+
NetworkType.connected // Any internet connection
73+
NetworkType.unmetered // WiFi or unlimited data only
74+
NetworkType.not_required // Can run without internet
75+
```
76+
77+
### Battery and Charging
78+
79+
```dart
80+
constraints: Constraints(
81+
requiresBatteryNotLow: true, // Wait for adequate battery
82+
requiresCharging: true, // Only run when plugged in
83+
)
84+
```
85+
86+
<Warning>
87+
**Platform Differences:** Some constraints are Android-only. iOS background tasks have different system-level constraints that cannot be configured directly.
88+
</Warning>
89+
90+
## Task Management
91+
92+
### Tagging Tasks
93+
94+
Group related tasks with tags for easier management:
95+
96+
```dart
97+
// Tag multiple related tasks
98+
Workmanager().registerOneOffTask(
99+
"sync-photos",
100+
"photo_sync",
101+
tag: "sync-tasks",
102+
);
103+
104+
Workmanager().registerOneOffTask(
105+
"sync-documents",
106+
"document_sync",
107+
tag: "sync-tasks",
108+
);
109+
110+
// Cancel all tasks with a specific tag
111+
Workmanager().cancelByTag("sync-tasks");
112+
```
113+
114+
### Canceling Tasks
115+
116+
```dart
117+
// Cancel a specific task by unique name
118+
Workmanager().cancelByUniqueName("sync-photos");
119+
120+
// Cancel tasks by tag
121+
Workmanager().cancelByTag("sync-tasks");
122+
123+
// Cancel all scheduled tasks
124+
Workmanager().cancelAll();
125+
```
126+
127+
### Task Scheduling Options
128+
129+
```dart
130+
// One-time task with delay
131+
Workmanager().registerOneOffTask(
132+
"delayed-task",
133+
"cleanup",
134+
initialDelay: Duration(minutes: 30),
135+
inputData: {'cleanupType': 'cache'}
136+
);
137+
138+
// Periodic task with custom frequency
139+
Workmanager().registerPeriodicTask(
140+
"hourly-sync",
141+
"data_sync",
142+
frequency: Duration(hours: 1), // Android: minimum 15 minutes
143+
initialDelay: Duration(minutes: 5), // Wait before first execution
144+
inputData: {'syncType': 'incremental'}
145+
);
146+
```
147+
148+
## Advanced Configuration
149+
150+
### Task Identification
151+
152+
Use meaningful, unique task names to avoid conflicts:
153+
154+
```dart
155+
// Good: Specific and unique
156+
Workmanager().registerOneOffTask(
157+
"user-${userId}-photo-upload-${timestamp}",
158+
"upload_task",
159+
inputData: {'userId': userId, 'type': 'photo'}
160+
);
161+
162+
// Avoid: Generic names that might conflict
163+
Workmanager().registerOneOffTask(
164+
"task1",
165+
"upload",
166+
// ...
167+
);
168+
```
169+
170+
### Task Types and Names
171+
172+
```dart
173+
// Use descriptive task type names in your callback
174+
@pragma('vm:entry-point')
175+
void callbackDispatcher() {
176+
Workmanager().executeTask((task, inputData) async {
177+
switch (task) {
178+
case 'photo_upload':
179+
return await handlePhotoUpload(inputData);
180+
case 'data_sync':
181+
return await handleDataSync(inputData);
182+
case 'cache_cleanup':
183+
return await handleCacheCleanup(inputData);
184+
case 'notification_check':
185+
return await handleNotificationCheck(inputData);
186+
default:
187+
print('Unknown task: $task');
188+
return Future.value(false);
189+
}
190+
});
191+
}
192+
```
193+
194+
## Error Handling and Retries
195+
196+
```dart
197+
@pragma('vm:entry-point')
198+
void callbackDispatcher() {
199+
Workmanager().executeTask((task, inputData) async {
200+
int retryCount = inputData?['retryCount'] ?? 0;
201+
202+
try {
203+
// Your task logic
204+
await performTask(inputData);
205+
return Future.value(true);
206+
207+
} catch (e) {
208+
print('Task failed: $e');
209+
210+
// Decide whether to retry
211+
if (retryCount < 3 && isRetryableError(e)) {
212+
print('Retrying task (attempt ${retryCount + 1})');
213+
return Future.value(false); // Tell system to retry
214+
} else {
215+
print('Task failed permanently');
216+
return Future.value(true); // Don't retry
217+
}
218+
}
219+
});
220+
}
221+
222+
bool isRetryableError(dynamic error) {
223+
// Network errors, temporary server issues, etc.
224+
return error.toString().contains('network') ||
225+
error.toString().contains('timeout');
226+
}
227+
```
228+
229+
## Best Practices
230+
231+
### Efficient Task Design
232+
233+
```dart
234+
// Good: Quick, focused tasks
235+
@pragma('vm:entry-point')
236+
void callbackDispatcher() {
237+
Workmanager().executeTask((task, inputData) async {
238+
// Fast operation
239+
await syncCriticalData();
240+
return Future.value(true);
241+
});
242+
}
243+
244+
// Avoid: Long-running operations
245+
@pragma('vm:entry-point')
246+
void callbackDispatcher() {
247+
Workmanager().executeTask((task, inputData) async {
248+
// This might timeout on iOS (30-second limit)
249+
await processLargeDataset(); // ❌ Too slow
250+
return Future.value(true);
251+
});
252+
}
253+
```
254+
255+
### Resource Management
256+
257+
```dart
258+
@pragma('vm:entry-point')
259+
void callbackDispatcher() {
260+
Workmanager().executeTask((task, inputData) async {
261+
HttpClient? client;
262+
263+
try {
264+
// Initialize resources in the background isolate
265+
client = HttpClient();
266+
267+
// Perform task
268+
await performNetworkOperation(client);
269+
270+
return Future.value(true);
271+
272+
} finally {
273+
// Clean up resources
274+
client?.close();
275+
}
276+
});
277+
}
278+
```
279+
280+
<Success>
281+
**Pro Tip:** Always initialize dependencies inside your background task callback since it runs in a separate isolate from your main app.
282+
</Success>

docs/quickstart.mdx

Lines changed: 2 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -213,65 +213,6 @@ Your background tasks can return:
213213
- `Future.value(false)` - 🔄 Task should be retried
214214
- `Future.error(...)` - ❌ Task failed
215215

216-
## Task Customization
217-
218-
### Input Data and Constraints
219-
220-
```dart
221-
// Schedule task with input data and constraints
222-
Workmanager().registerOneOffTask(
223-
"upload-task",
224-
"file_upload",
225-
initialDelay: Duration(minutes: 5),
226-
inputData: {
227-
'fileName': 'document.pdf',
228-
'uploadUrl': 'https://api.example.com/upload',
229-
'retryCount': 3
230-
},
231-
constraints: Constraints(
232-
networkType: NetworkType.connected,
233-
requiresBatteryNotLow: true,
234-
requiresCharging: false,
235-
requiresDeviceIdle: false,
236-
requiresStorageNotLow: true,
237-
),
238-
);
239-
240-
// Access input data in your task
241-
@pragma('vm:entry-point')
242-
void callbackDispatcher() {
243-
Workmanager().executeTask((task, inputData) async {
244-
print('Task: $task');
245-
print('Input: $inputData'); // Access your input data
246-
247-
String? fileName = inputData?['fileName'];
248-
int retryCount = inputData?['retryCount'] ?? 0;
249-
250-
// Your task logic using the input data
251-
return Future.value(true);
252-
});
253-
}
254-
```
255-
256-
### Task Tagging and Management
257-
258-
```dart
259-
// Tag tasks for easier management
260-
Workmanager().registerOneOffTask(
261-
"sync-task-1",
262-
"data_sync",
263-
tag: "data-sync-tasks",
264-
);
265-
266-
// Cancel tasks by tag
267-
Workmanager().cancelByTag("data-sync-tasks");
268-
269-
// Cancel specific task
270-
Workmanager().cancelByUniqueName("sync-task-1");
271-
272-
// Cancel all tasks
273-
Workmanager().cancelAll();
274-
```
275216

276217
## Key Points
277218

@@ -287,5 +228,6 @@ For comprehensive debugging guidance including platform-specific tools, ADB comm
287228

288229
## Next Steps
289230

290-
- **[Debugging Guide](debugging)** - Learn how to debug and troubleshoot background tasks
231+
- **[Task Customization](customization)** - Advanced configuration with constraints, input data, and management
232+
- **[Debugging Guide](debugging)** - Learn how to debug and troubleshoot background tasks
291233
- **[Example App](https://github.com/fluttercommunity/flutter_workmanager/tree/main/example)** - Complete working demo

0 commit comments

Comments
 (0)