Флаттер - Как вычислить тяжелую задачу, которая включает будущее, не блокируя пользовательский интерфейс?

Я создаю приложение, которое извлекает сообщения из Интернета как 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

Пакет изолятов предоставляет некоторые удобные функции, облегчающие работу с изолятами.

Другие вопросы по тегам