Skip to content

Commit 1afef5f

Browse files
Offload Task JSON encoding and decoding to isolate
Moved JSON serialization and deserialization for `Task` and `TaskStatusUpdate` objects to a background isolate using `compute`. This change impacts `NativeDownloader`'s `initialize`, `allTasks`, and `initCallbackDispatcher` methods to prevent blocking the main thread during heavy JSON operations. - Added static helper methods to `NativeDownloader` for isolate-safe JSON handling. - Updated `methodCallHandler` and `allTasks` to use asynchronous `compute` calls. - Updated `initCallbackDispatcher` to decode arguments and encode return values using `compute`.
1 parent 56a48dd commit 1afef5f

File tree

1 file changed

+54
-18
lines changed

1 file changed

+54
-18
lines changed

lib/src/native_downloader.dart

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ abstract base class NativeDownloader extends BaseDownloader {
4040
final args = call.arguments as List<dynamic>;
4141
var taskJsonString = args.first as String;
4242
final task = taskJsonString.isNotEmpty
43-
? Task.createFromJson(jsonDecode(taskJsonString))
43+
? await compute(_taskFromJson, taskJsonString)
4444
: DownloadTask(url: 'url');
4545
final message = (
4646
call.method,
@@ -184,8 +184,7 @@ abstract base class NativeDownloader extends BaseDownloader {
184184

185185
// from ParallelDownloadTask
186186
case ('enqueueChild', String childTaskJsonString):
187-
final childTask =
188-
Task.createFromJson(jsonDecode(childTaskJsonString));
187+
final childTask = await compute(_taskFromJson, childTaskJsonString);
189188
Future.delayed(const Duration(milliseconds: 100))
190189
.then((_) => FileDownloader().enqueue(childTask));
191190

@@ -197,12 +196,8 @@ abstract base class NativeDownloader extends BaseDownloader {
197196

198197
// from ParallelDownloadTask
199198
case ('pauseTasks', String listOfTasksJson):
200-
final listOfTasks = List<DownloadTask>.from(jsonDecode(
201-
listOfTasksJson,
202-
reviver: (key, value) => switch (key) {
203-
int _ => Task.createFromJson(value as Map<String, dynamic>),
204-
_ => value
205-
}));
199+
final listOfTasks =
200+
await compute(_downloadTaskListFromJson, listOfTasksJson);
206201
Future.delayed(const Duration(milliseconds: 100)).then((_) async {
207202
for (final chunkTask in listOfTasks) {
208203
await FileDownloader().pause(chunkTask);
@@ -283,9 +278,7 @@ abstract base class NativeDownloader extends BaseDownloader {
283278
final result = await methodChannel.invokeMethod<List<dynamic>?>(
284279
'allTasks', allGroups ? null : group) ??
285280
[];
286-
final tasks = result
287-
.map((e) => Task.createFromJson(jsonDecode(e as String)))
288-
.toList();
281+
final tasks = await compute(_taskListFromListStrings, result);
289282
return [...retryAndPausedTasks, ...tasks];
290283
}
291284

@@ -516,6 +509,46 @@ abstract base class NativeDownloader extends BaseDownloader {
516509
}
517510
return (configItem.$1, ''); // normal result
518511
}
512+
513+
/// Helper to create a Task from a JSON string, for use with [compute]
514+
static Task _taskFromJson(String jsonString) {
515+
return Task.createFromJson(jsonDecode(jsonString));
516+
}
517+
518+
/// Helper to create a list of DownloadTasks from a JSON string, for use with [compute]
519+
///
520+
/// Used for the 'pauseTasks' message
521+
static List<DownloadTask> _downloadTaskListFromJson(String jsonString) {
522+
return List<DownloadTask>.from(jsonDecode(jsonString,
523+
reviver: (key, value) => switch (key) {
524+
int _ => Task.createFromJson(value as Map<String, dynamic>),
525+
_ => value
526+
}));
527+
}
528+
529+
/// Helper to create a list of Tasks from a list of JSON strings, for use with [compute]
530+
///
531+
/// Used for the 'allTasks' message
532+
static List<Task> _taskListFromListStrings(List<dynamic> jsonStrings) {
533+
return jsonStrings
534+
.map((e) => Task.createFromJson(jsonDecode(e as String)))
535+
.toList();
536+
}
537+
538+
/// Helper to create a TaskStatusUpdate from a JSON string, for use with [compute]
539+
static TaskStatusUpdate _taskStatusUpdateFromJson(String jsonString) {
540+
return TaskStatusUpdate.fromJsonString(jsonString);
541+
}
542+
543+
/// Helper to encode a Task to a JSON string, for use with [compute]
544+
static String _taskToJsonString(Task task) {
545+
return jsonEncode(task.toJson());
546+
}
547+
548+
/// Helper to encode a TaskStatusUpdate to a JSON string, for use with [compute]
549+
static String _taskStatusUpdateToJsonString(TaskStatusUpdate update) {
550+
return jsonEncode(update.toJson());
551+
}
519552
}
520553

521554
/// Android native downloader
@@ -733,31 +766,34 @@ void initCallbackDispatcher() {
733766
switch (call.method) {
734767
case 'beforeTaskStartCallback':
735768
final taskJsonString = call.arguments as String;
736-
final task = Task.createFromJson(jsonDecode(taskJsonString));
769+
final task =
770+
await compute(NativeDownloader._taskFromJson, taskJsonString);
737771
final callBack = task.options?.beforeTaskStartCallBack;
738772
final taskStatusUpdate = await callBack?.call(task);
739773
if (taskStatusUpdate == null) {
740774
return null;
741775
}
742-
return jsonEncode(taskStatusUpdate.toJson());
776+
return await compute(
777+
NativeDownloader._taskStatusUpdateToJsonString, taskStatusUpdate);
743778

744779
case 'onTaskStartCallback':
745780
case 'onAuthCallback':
746781
final taskJsonString = call.arguments as String;
747-
final task = Task.createFromJson(jsonDecode(taskJsonString));
782+
final task =
783+
await compute(NativeDownloader._taskFromJson, taskJsonString);
748784
final callBack = call.method == 'onTaskStartCallback'
749785
? task.options?.onTaskStartCallBack
750786
: task.options?.auth?.onAuthCallback;
751787
final newTask = await callBack?.call(task);
752788
if (newTask == null) {
753789
return null;
754790
}
755-
return jsonEncode(newTask.toJson());
791+
return await compute(NativeDownloader._taskToJsonString, newTask);
756792

757793
case 'onTaskFinishedCallback':
758794
final taskUpdateJsonString = call.arguments as String;
759-
final taskStatusUpdate =
760-
TaskStatusUpdate.fromJsonString(taskUpdateJsonString);
795+
final taskStatusUpdate = await compute(
796+
NativeDownloader._taskStatusUpdateFromJson, taskUpdateJsonString);
761797
final callBack = taskStatusUpdate.task.options?.onTaskFinishedCallBack;
762798
await callBack?.call(taskStatusUpdate);
763799
return null;

0 commit comments

Comments
 (0)