Канал Friflex о разработке на Flutter. Обновления, плагины, полезные материалы — превращаем знания в реальный опыт, доступный каждому разработчику.
🔗 Наш канал для разработчиков: @friflex_dev
🔗 Канал о продуктовой разработке: @friflex_product
Post #261
684
🌟Всем привет! Это Анна, Flutter Team Lead Friflex
Наверняка каждый Flutter-разработчик знает, что такое Isolate и как он работает. Немного освежим теорию в памяти.
Dart — однопоточный язык программирования. Когда мы создаем Flutter-приложения, все вычисления и операции выполняются по умолчанию в основном и единственном потоке — изоляте (Isolate).
При необходимости разработчик может запустить дополнительный изолят. Например, когда требуется произвести операции, которые могут занять достаточно времени, ресурсов и повлиять на производительность приложения. Сюда можно отнести какие-то сложные вычисления, а также парсинг огромного объема данных. Благодаря вынесению этих функций в отдельный изолят, основной поток не блокируется, интерфейс приложения остается отзывчивым.
В Dart изоляты можно запускать тремя основными способами:
1️⃣
2️⃣
3️⃣
Уверена, простые примеры вы легко сможете найти в интернете или реализовать сами. А сейчас в качестве примера рассмотрим более сложную задачу.
Представим, что мы получаем большой список карточек товаров с бэкенда. Мы знаем, что некоторые данные в карточках могут быть невалидны и привести к ошибке парсинга. В таком случае нам нужно выполнить парсинг списка данных в отдельном изоляте, при этом ошибка парсинга одной карточки не должна прервать весь процесс — нам нужно лишь пропустить этот объект и залогировать сведения о проблеме.
В решении этой задачи нам поможет
Шаг 1. Создаем top-level метод парсинга данных в изоляте
Шаг 2. Создаем метод получения данных fetchData(). В нем выполняем запрос на бэкенд. Дальнейшие шаги будут дополнять этот метод
3 шаг. После получения данных создаем два порта ReceivePort(). Один порт будет отвечать за передачу обработанных объектов, второй — за передачу данных о локальных ошибках парсинга
Шаг 4. Открываем новый изолят и запускаем в нем метод
Продолжение в комментариях👇
Наверняка каждый Flutter-разработчик знает, что такое Isolate и как он работает. Немного освежим теорию в памяти.
Dart — однопоточный язык программирования. Когда мы создаем Flutter-приложения, все вычисления и операции выполняются по умолчанию в основном и единственном потоке — изоляте (Isolate).
При необходимости разработчик может запустить дополнительный изолят. Например, когда требуется произвести операции, которые могут занять достаточно времени, ресурсов и повлиять на производительность приложения. Сюда можно отнести какие-то сложные вычисления, а также парсинг огромного объема данных. Благодаря вынесению этих функций в отдельный изолят, основной поток не блокируется, интерфейс приложения остается отзывчивым.
В Dart изоляты можно запускать тремя основными способами:
1️⃣
Isolate.run() — метод запустит новый изолят, в котором будет выполнена переданная функция. По завершении операций из изолята вернутся ожидаемые данные, а поток самостоятельно завершится2️⃣
Isolate.spawn() — также запускает новый изолят, в который необходимо передавать функцию для выполнения. При этом в отличие от изолята, запущенного через run(), дает возможность непрерывно обмениваться сообщениями с основным потоком3️⃣
Isolate.spawnUri() — работает аналогично spawn() за одним исключением. В изолят можно отправить прямую ссылку на Dart-программу. Уверена, простые примеры вы легко сможете найти в интернете или реализовать сами. А сейчас в качестве примера рассмотрим более сложную задачу.
Представим, что мы получаем большой список карточек товаров с бэкенда. Мы знаем, что некоторые данные в карточках могут быть невалидны и привести к ошибке парсинга. В таком случае нам нужно выполнить парсинг списка данных в отдельном изоляте, при этом ошибка парсинга одной карточки не должна прервать весь процесс — нам нужно лишь пропустить этот объект и залогировать сведения о проблеме.
В решении этой задачи нам поможет
Isolate.spawn() и порты получения данных ReceivePort(). Шаг 1. Создаем top-level метод парсинга данных в изоляте
_parseInIsolate(). Метод должен принимать обязательно два порта отправки данных — порт отправки результата парсинга и порт отправки ошибок. Именно в этом методе мы закладываем логику обработки ошибки. В случае перехвата ошибки, отправляем ее в порт ошибок errorSendPortFuture<void> _parseInIsolate(
({
SendPort dataSendPort,
SendPort errorSendPort,
List<Map<String, dynamic>> rawDataList,
}) params,
) async {
final result = <ResultEntity>[];
for (final data in params.rawDataList) {
try {
// здесь выполняем парсинг каждого элемента
result.add(...);
} on Object catch (error, stackTrace) {
// в случае ошибки парсинга конкретного объекта
// отправляем ошибку обратно в главный изолят
params.errorSendPort.send((error: error, stackTrace: stackTrace));
continue;
}
}
// в порт данных отправляем готовые объекты
params.dataSendPort.send(result);
}
Шаг 2. Создаем метод получения данных fetchData(). В нем выполняем запрос на бэкенд. Дальнейшие шаги будут дополнять этот метод
Future<List<ResultEntity>> fetchData() async {
final rawDataList = await _httpClient.get('v1/examples/data');
}
3 шаг. После получения данных создаем два порта ReceivePort(). Один порт будет отвечать за передачу обработанных объектов, второй — за передачу данных о локальных ошибках парсинга
final dataPort = ReceivePort();
final errorPort = ReceivePort();
Шаг 4. Открываем новый изолят и запускаем в нем метод
_parseInIsolate(). Обязательно передаем в него два порта отправки и данные, которые надо обработать
final isolate = await Isolate.spawn(
_parseInIsolate,
(
dataSendPort: dataPort.sendPort,
errorSendPort: errorPort.sendPort,
rawDataList: rawDataList,
),
);
Продолжение в комментариях👇
- ❤ 10
- 🔥 7
- 👌 1








