|
@@ -7,6 +7,7 @@ class HttpGetImage {
|
|
|
final String url;
|
|
final String url;
|
|
|
final int count;
|
|
final int count;
|
|
|
final Map<String, String>? httpHeaders;
|
|
final Map<String, String>? httpHeaders;
|
|
|
|
|
+
|
|
|
HttpGetImage({
|
|
HttpGetImage({
|
|
|
required this.url,
|
|
required this.url,
|
|
|
required this.count,
|
|
required this.count,
|
|
@@ -16,77 +17,79 @@ class HttpGetImage {
|
|
|
Future<Uint8List> getDataObjectIsolate() async {
|
|
Future<Uint8List> getDataObjectIsolate() async {
|
|
|
final ReceivePort receivePort = ReceivePort();
|
|
final ReceivePort receivePort = ReceivePort();
|
|
|
|
|
|
|
|
- var data = {'sendPort': receivePort.sendPort, 'url': url, 'count': count};
|
|
|
|
|
-
|
|
|
|
|
- if (httpHeaders != null) {
|
|
|
|
|
- data = {
|
|
|
|
|
- 'sendPort': receivePort.sendPort,
|
|
|
|
|
- 'url': url,
|
|
|
|
|
- 'headers': httpHeaders!,
|
|
|
|
|
- 'count': count,
|
|
|
|
|
- };
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- final Isolate isolate = await Isolate.spawn(_isolateFetchVideo, data);
|
|
|
|
|
|
|
+ final data = {
|
|
|
|
|
+ 'sendPort': receivePort.sendPort,
|
|
|
|
|
+ 'url': url,
|
|
|
|
|
+ 'count': count,
|
|
|
|
|
+ if (httpHeaders != null) 'headers': httpHeaders!,
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
|
|
+ // Чтобы избежать утечек памяти, используем try-finally для закрытия порта
|
|
|
|
|
+ Isolate? isolate;
|
|
|
try {
|
|
try {
|
|
|
|
|
+ isolate = await Isolate.spawn(_isolateFetchVideo, data);
|
|
|
final dynamic result = await receivePort.first;
|
|
final dynamic result = await receivePort.first;
|
|
|
- isolate.kill();
|
|
|
|
|
|
|
|
|
|
if (result is Uint8List) {
|
|
if (result is Uint8List) {
|
|
|
return result;
|
|
return result;
|
|
|
} else {
|
|
} else {
|
|
|
- throw Exception();
|
|
|
|
|
|
|
+ throw Exception("Failed to load image bytes or received null");
|
|
|
}
|
|
}
|
|
|
- } catch (e) {
|
|
|
|
|
- isolate.kill();
|
|
|
|
|
- throw Exception();
|
|
|
|
|
} finally {
|
|
} finally {
|
|
|
|
|
+ isolate?.kill(priority: Isolate.immediate);
|
|
|
receivePort.close();
|
|
receivePort.close();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- Future<void> _isolateFetchVideo(Map<String, dynamic> message) async {
|
|
|
|
|
|
|
+ // Обязательно делаем функцию STATIC, чтобы изолят мог её запустить без контекста класса
|
|
|
|
|
+ static Future<void> _isolateFetchVideo(Map<String, dynamic> message) async {
|
|
|
final SendPort sendPort = message['sendPort'];
|
|
final SendPort sendPort = message['sendPort'];
|
|
|
final String url = message['url'];
|
|
final String url = message['url'];
|
|
|
- int count = message['count'];
|
|
|
|
|
- Map<String, String>? headers = message.containsKey("headers")
|
|
|
|
|
- ? message['headers']
|
|
|
|
|
- : null;
|
|
|
|
|
|
|
+ final int count = message['count'];
|
|
|
|
|
+ final Map<String, String>? headers =
|
|
|
|
|
+ message['headers'] as Map<String, String>?;
|
|
|
|
|
|
|
|
int time = 10;
|
|
int time = 10;
|
|
|
- late http.Response response;
|
|
|
|
|
|
|
|
|
|
- do {
|
|
|
|
|
- if (time > count) {
|
|
|
|
|
- sendPort.send(null);
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // Заменяем do-while на контролируемый цикл по попыткам
|
|
|
|
|
+ while (time <= count) {
|
|
|
try {
|
|
try {
|
|
|
- response = await http
|
|
|
|
|
|
|
+ final response = await http
|
|
|
.get(Uri.parse(url), headers: headers)
|
|
.get(Uri.parse(url), headers: headers)
|
|
|
.timeout(Duration(seconds: time));
|
|
.timeout(Duration(seconds: time));
|
|
|
|
|
|
|
|
if (response.statusCode == 200) {
|
|
if (response.statusCode == 200) {
|
|
|
- try {
|
|
|
|
|
- if (response.body.isNotEmpty) {
|
|
|
|
|
|
|
+ if (response.body.isNotEmpty) {
|
|
|
|
|
+ try {
|
|
|
final data = jsonDecode(response.body);
|
|
final data = jsonDecode(response.body);
|
|
|
-
|
|
|
|
|
if (data is Map) {
|
|
if (data is Map) {
|
|
|
|
|
+ // Если пришел JSON вместо сырых байт картинки
|
|
|
sendPort.send(null);
|
|
sendPort.send(null);
|
|
|
- break;
|
|
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
|
|
+ } catch (_) {
|
|
|
|
|
+ // Если это не JSON (значит, скорее всего, чистые байты картинки) — всё отлично
|
|
|
}
|
|
}
|
|
|
- } catch (e) {}
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
sendPort.send(response.bodyBytes);
|
|
sendPort.send(response.bodyBytes);
|
|
|
- break;
|
|
|
|
|
|
|
+ return; // Успешно выходим из функции
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // Если код не 200 (например 500), увеличиваем таймаут и пробуем снова
|
|
|
time++;
|
|
time++;
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
- sendPort.send(null);
|
|
|
|
|
|
|
+ // Если поймали TimeoutException или SocketException:
|
|
|
|
|
+ // В дебаге это частая история. Увеличиваем время и идем на следующую итерацию.
|
|
|
|
|
+ time++;
|
|
|
|
|
+ if (time > count) {
|
|
|
|
|
+ sendPort.send(null);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- } while (response.statusCode != 200);
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Если превысили лимит count и ничего не вернули
|
|
|
sendPort.send(null);
|
|
sendPort.send(null);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|