等待Dart异步功能完成

时间:2019-07-21 18:44:00

标签: android flutter dart

我正在业余时间在Android上试用Flutter,但我正努力让玩具Mandelbrot应用程序等待异步功能完成。

我已经设计了Widget构建方法,以显示圆形进度指示器,直到计算出Mandelbrot点为止(这需要几秒钟)-它检查布尔值标志“ _gotPointValues”,并显示进度指示器是否为假。

问题在于async / await机制不等待长时间运行的计算完成。

从行执行:

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);
    }

}

2 个答案:

答案 0 :(得分:0)

尝试更改void _getMandelbrotPoints()异步 到未来_getMandelbrotPoints()异步

答案 1 :(得分:0)

即使calculateMandelbrotPoints()是一个异步函数,并且进行了大量计算,也并不意味着执行将花费很长时间,在这种情况下,它并不需要。它执行速度很快,您可以立即获得结果。

我为您编写了两个函数来演示这一点,您可以在此dart pad

中使用它们