等待 Dart 异步函数完成
Posted
技术标签:
【中文标题】等待 Dart 异步函数完成【英文标题】:Waiting for a Dart async function to complete 【发布时间】:2019-11-29 20:09:51 【问题描述】:我在业余时间尝试在 android 上使用 Flutter,我正在努力让一个玩具 Mandelbrot 应用程序等待异步函数完成。
我已经设计了我的 Widget 构建方法来显示一个循环进度指示器,直到计算出 Mandelbrot 点(这需要几秒钟) - 它检查一个布尔标志“_gotPointValues”并在它为假时显示进度指示器。
问题在于异步/等待机制不会等待长时间运行的计算完成。
从行执行:
print("** 从异步未来获取数据 **");
.. 进入 MandelbrotWidgetState._getMandelbrotPoints 函数后立即继续。
我确定我遗漏了一些非常明显的东西 - 如果有人能发现我做错了什么,感谢任何帮助。
谢谢。
import 'package:flutter/material.dart';
import 'package:phil_flutter_app/mandelbrot_painter.dart';
import 'package:phil_flutter_app/mandelbrot_points.dart';
/// This class defines a Mandelbrot widget.
class MandelbrotWidget extends StatefulWidget
@override
MandelbrotWidgetState createState()
return MandelbrotWidgetState();
/// This class defines a Mandelbrot widget state.
class MandelbrotWidgetState extends State<MandelbrotWidget>
int _pointsWidth;
int _pointsHeight;
int _maxIterations;
MandelbrotPoints _mandelbrotPoints;
MandelbrotPainter _mandelbrotPainter;
List _pointValues;
bool _gotPointValues;
/// Initialise.
void initState()
super.initState();
print("initState");
_pointsWidth = 1080;
_pointsHeight = 1920;
_maxIterations = 256;
_mandelbrotPoints = new MandelbrotPoints(_pointsWidth, _pointsHeight, _maxIterations);
_mandelbrotPainter = new MandelbrotPainter(_pointsWidth, _pointsHeight);
_pointValues = null;
_gotPointValues = false;
_getMandelbrotPoints();
/// Get the mandelbrot points.
void _getMandelbrotPoints() async
_pointValues = await _mandelbrotPoints.calculateMandelbrotPoints();
print("** Got data from async future **");
setState(()
_gotPointValues = true;
);
@override
Widget build(BuildContext context)
print("build");
_mandelbrotPainter.setDevicePixelRatio(MediaQuery.of(context).devicePixelRatio);
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
title: Text("PH - Mandelbrot Test - Google Flutter"),
centerTitle: true
),
body: _buildBody(),
floatingActionButton: new FloatingActionButton(
onPressed: _redraw,
tooltip: 'Refresh',
child: Icon(Icons.refresh),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat
);
/// Build the body.
Widget _buildBody()
if (_gotPointValues)
print("** Building fractal **");
_mandelbrotPainter.setPointValues(_pointValues);
return new Center(
child: new CustomPaint(
painter: _mandelbrotPainter,
child: Center()
)
);
else
print("** Building progress indicator **");
return new Center(
child: new CircularProgressIndicator()
);
/// Redraw.
void _redraw()
_mandelbrotPainter.repaint();
/// This class calculates points for the Mandelbrot fractal.
class MandelbrotPoints
int width;
int height;
int _maxIterations;
/// Constructor.
MandelbrotPoints(int width, int height, int _maxIterations)
this.width = width;
this.height = height;
this._maxIterations = _maxIterations;
/// Calculate the Mandelbrot points.
Future<List> calculateMandelbrotPoints() async
print("MandelbrotPoints.calculateMandelbrotPoints");
int w = width;
int h = height;
List _pointValues = new List.generate(w, (i)
=> new List(h));
int xOffset = 0;
int yOffset = -(h ~/ 6);
double zoom = 0.8;
for (int x = 0; x < w; x ++)
for (int y = 0; y < h; y ++)
double cRe = 1.5 * (y + yOffset - h / 2) / (0.5 * zoom * h);
double cIm = 1.0 * (x + xOffset - w / 2) / (0.5 * zoom * w);
double zx = 0;
double zy = 0;
int iteration = 0;
while (zx * zx + zy * zy <= 4 && iteration < _maxIterations)
double zyNew = zy * zy - zx * zx + cRe;
zx = 2 * zx * zy + cIm;
zy = zyNew;
iteration ++;
if (iteration < _maxIterations)
_pointValues[x][y] = iteration;
else
_pointValues[x][y] = -1;
return _pointValues;
import 'dart:math';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:phil_flutter_app/mandelbrot_colour_utils.dart';
/// This class defines a custom painter
/// to draw a Mandelbrot fractal.
class MandelbrotPainter extends CustomPainter
int _pointsWidth;
int _pointsHeight;
List _pointValues;
Random _random;
MandelbrotColorUtils _mandelbrotColorUtils;
int _randomHue;
Size _size;
Canvas _canvas;
double _devicePixelRatio;
Paint _paint;
double _width;
double _height;
/// Constructor.
MandelbrotPainter(int _pointsWidth, int _pointsHeight)
print("MandelbrotPainter constructor");
this._pointsWidth = _pointsWidth;
this._pointsHeight = _pointsHeight;
_random = new Random();
_mandelbrotColorUtils = new MandelbrotColorUtils();
_randomHue = _getRandomNumber(0, 255);
_canvas = null;
_width = -1;
_height = -1;
_paint = null;
/// Set the device pixel ratio.
void setDevicePixelRatio(double devicePixelRatio)
_devicePixelRatio = devicePixelRatio;
@override
void paint(Canvas canvas, Size size)
print("paint");
_size = size;
_width = size.width;
_height = (size.height * 0.86);
_canvas = canvas;
_paint = Paint();
_paint.strokeWidth = 1;
_paint.style = PaintingStyle.fill;
_randomHue = _getRandomNumber(0, 255);
_drawMandelbrotPoints();
/// Repaint.
void repaint()
paint(_canvas, _size);
/// Set the point values.
void setPointValues(List _pointValues)
this._pointValues = _pointValues;
/// Draw the Mandelbrot points.
void _drawMandelbrotPoints()
print("_drawMandelbrotPoints");
_paint.color = Colors.black;
_canvas.drawRect(Rect.fromLTWH(0, 0, _width, _height), _paint);
int w = (_width * _devicePixelRatio).round();
int h = (_height * _devicePixelRatio).round();
for (int x = 0; x < _pointsWidth; x ++)
for (int y = 0; y < _pointsHeight; y ++)
int pixelValue = _pointValues[x][y];
if (pixelValue == -1)
_paint.color = Color.fromARGB(255, 0, 0, 0);
else
double h = ((2 * pixelValue) + _randomHue).toDouble();
_paint.color =
_mandelbrotColorUtils.createColorFromHsv(h, 100, 100);
List<Offset> points = new List();
int pointX = (x * (w / _pointsWidth)).round();
int pointY = (y * (h / _pointsHeight)).round();
points.add(Offset(pointX.toDouble() / _devicePixelRatio,
pointY.toDouble() / _devicePixelRatio));
_canvas.drawPoints(PointMode.points, points, _paint);
@override
bool shouldRepaint(CustomPainter oldDelegate)
return true;
/// Get a random number.
int _getRandomNumber(int min, int max)
return min + _random.nextInt(max - min);
【问题讨论】:
在异步调用中使用 AWAIT 请贴出整个代码。帮助您更容易。 谢谢,编辑原始帖子以包含所有代码。 【参考方案1】:即使calculateMandelbrotPoints()
是一个异步函数,并且进行了大量计算,但这并不意味着它会花费太长时间来执行,在这种情况下它不会。它执行速度很快,您可以立即获得结果。
我写了两个函数给你演示一下,你可以在这个dart pad玩玩
【讨论】:
谢谢,你是对的,我在那里猜错了。实际上,画家类中的 _drawMandelbrotPoints() 占用了大部分时间。我正在重写整个东西,感谢飞镖垫的例子,它应该对异步的东西有用。【参考方案2】:尝试更改 void _getMandelbrotPoints() 异步 到 Future _getMandelbrotPoints() 异步
【讨论】:
以上是关于等待 Dart 异步函数完成的主要内容,如果未能解决你的问题,请参考以下文章