Ищу синхронную альтернативу методу Flutter .Метод toImage()

#flutter #async-await #flame

#flutter #асинхронное ожидание #пламя

Вопрос:

На данный момент я экспериментирую с Flutter и игровым движком Flame. Для этого я расширяю базовый класс Flame и выполняю некоторую сложную обработку внутри его конструктора. Тяжелая обработка включает в себя составление изображения из других изображений и окончательное нанесение его на временный холст, а результат сохраняется в объекте Picture .

 ui.PictureRecorder rec = new ui.PictureRecorder();
Canvas tempCanvas = new Canvas(rec, bgRect);
// left out picture operations
ui.Picture pic = rec.endRecording();
  

Чтобы, наконец, получить объект изображения, мне нужно вызвать асинхронный .Метод toData(), который возвращает будущее.
Я завершаю вызов в асинхронном методе getImage()

 getImage(ui.Picture pic, Rect bgRect) async {
    background = await pic.toImage(bgRect.width.toInt(), bgRect.height.toInt());
    done = true;
}
  

(background — это переменная класса типа Image, которая используется внутри метода render() базового класса)

Проблема в том, что из-за асинхронности остальные мои операторы внутри конструктора игры выполняются, и после его завершения срабатывает метод render(), но фон может быть еще недоступен. Чтобы обойти это, я добавил переменную класса done типа bool, для которой устанавливается значение true внутри метода getImage(). Теперь я изменил функцию render(), чтобы дождаться, пока значение done станет true .

 void render(Canvas canvas) {
    if (done) {
        canvas.drawImage(background, new Offset(0.0, 0.0), new Paint());
    }
}
  

Конечно, это не слишком элегантно.
Есть ли способ дождаться .Метод toImage() для завершения внутри функции конструктора расширенного базового класса?
Я попытался сделать конструктор асинхронным, например:

 class TheGame extends BaseGame {
    Image background;
    bool done = false;

    TheGame(DeviceOrientation orientation) async {  
    }
}
  

но это выдает ошибку:

Модификатор ‘async’ не может быть применен к телу конструктора

Что еще я мог бы попытаться сделать его «синхронным»?

Ответ №1:

Если вам действительно нужно изображение до рендеринга первого кадра, вы можете просто создать статический метод, который отвечает за создание TheGame

 class TheGame extends BaseGame {
    final Image background;

    TheGame._(DeviceOrientation orientation, this.background);

    static Future<TheGame> create(DeviceOrientation orientation) async {
      return TheGame._(orientation, await generateImage());
    }
}
  

но я предполагаю, что это действительно не повредит, если вы визуализируете несколько кадров без фонового изображения, тогда я бы посоветовал вам просто проверить background != null вместо done свойства, которое кажется немного избыточным.

Комментарии:

1. Спасибо! Это интересная идея. Нет, мне просто интересно, что означает подчеркивание в TheGame._ ?

2. это просто способ сделать конструктор закрытым.. итак, нет, класс не может быть создан из другого файла напрямую, но должен вызывать статический метод.