Флаттер - Как вычислить тяжелую задачу, которая включает будущее, не блокируя пользовательский интерфейс?
Я создаю приложение, которое извлекает сообщения из Интернета как JSON. Я анализирую json в Post объекты в флаттер, используя фабрику. Объект Post включает заголовок, тело и изображение. Я отображаю эти сообщения в виде списка с помощью построителя списка. Тяжелая задача состоит в том, чтобы я вычислил 2 доминирующих цвета из изображения, чтобы установить в качестве фонового градиента элемента сообщения. Для этого я использую: https://pub.dartlang.org/packages/palette_generator
Я вычисляю 2 доминирующих цвета в фабрике парсеров json, потому что тогда у меня есть полный объект Post со всей необходимой информацией. Также, таким образом, мне не нужно вычислять цвета при рендеринге объекта Post. Я делаю это с помощью следующего кода:
Future<List> _getColors() async {
Color gradientOne, gradientTwo;
String imageUrl = json['image'];
paletteGenerator = await PaletteGenerator.fromImageProvider(
CachedNetworkImageProvider(imageUrl));
gradientOne = paletteGenerator.colors.toList()[0];
gradientTwo = paletteGenerator.colors.toList()[1];
return [gradientOne, gradientTwo];
}
Я добавляю это к объекту Post и в рендере я жду этого будущего:
post.gradientColors
.then((result) => {
gradient = result,
this.setState(() {
loading = false;
})
})
В основном интерфейсе я показываю индикатор загрузки, пока все фьючерсы не будут разрешены. Для этого я использую следующий код:
List<Future> futures = [];
for (var post in tmpList) {
futures.add(post.gradientColors);
}
await Future.wait(futures)
.then((result) => {list.addAll(tmpList)});
}
Это работает нормально, за исключением медленного интерфейса при получении новых сообщений. После небольшого прочтения я обнаружил, что могу использовать изоляты во флаттере. Поэтому я изменил свою функцию синтаксического анализа, как описано здесь: https://flutter.io/docs/cookbook/networking/background-parsing
Это работает безупречно, и мое приложение работает без каких-либо задержек, недостатком является то, что мои цвета не рассчитываются. По какой-то причине, когда я использую compute(), мое будущее никогда не приходит к результату.
Можно ли использовать вычисления в этой ситуации или есть лучший способ рассчитать цвета, не вызывая задержки в моем пользовательском интерфейсе?
РЕДАКТИРОВАТЬ
Я пытался программировать Isolate без вычислений, но цветовые фьючерсы все еще не загружаются. Это код, который я использовал:
ReceivePort receivePort = ReceivePort();
Isolate isolate = await Isolate.spawn(getMorePosts, receivePort.sendPort);
receivePort.listen((data) {
list.addAll(data);
});
Я все данные получаю, но мое будущее не заканчивается.
1 ответ
К несчастью compute()
поддерживает только результаты синхронизации.
compute()
прост и является просто оберткой, чтобы упростить запуск изолятов.
Вы можете просто начать дополнительную изоляцию, используя пользовательский код и получить больше мощности.
https://api.dartlang.org/stable/2.1.1/dart-isolate/dart-isolate-library.html
Пакет изолятов предоставляет некоторые удобные функции, облегчающие работу с изолятами.