使用 FutureBuilder 实现 Flutter 异步口吃

问题描述 投票:0回答:1

所以我正在尝试使用图像库制作一个 Voronoi 图应用程序。所以这个算法非常慢,所以当按下按钮时,我希望我不要口吃并显示 CircularProgressindicator,然后当计算完成并且图像准备就绪时,我想查看 Uint8List 中的图像

class _VoronoiPageState extends State<VoronoiPage> {

  final TextEditingController textEditingControllerWidth = TextEditingController();
  final TextEditingController textEditingControllerHeight = TextEditingController();
  final TextEditingController textEditingControllerStations = TextEditingController();
  Future<Uint8List> ?diagramImage;
  

  Uint8List createDiagram() {
    
    int width = 0;
    int height = 0;
    int basedStation = 0;
    setState(() {
    width = int.tryParse(textEditingControllerWidth.text) ?? 0;
    height = int.tryParse(textEditingControllerHeight.text) ?? 0;
    basedStation = int.tryParse(textEditingControllerStations.text) ?? 0;
    });
    
    // Creating new image
    img.Image diagram = img.Image(width: width, height: height);
    print('image created');
    List<DrawPixels> baseStationList = generatePixels(basedStation, width, height);
    for (var pixel in baseStationList) {
      pixel.color = generateRandomColor();
    }
    // Drawingf the diagram
    for (int i = 0; i < width; i++) {
      for (int j = 0; j < height; j++) {
        double minDistance = double.infinity;
        int minIndex = -1;
        for (int k = 0; k < basedStation; k++) {
          double distance = calculateDistance(i, j, baseStationList[k].x, baseStationList[k].y);
          if (distance < minDistance) {
            minDistance = distance;
            minIndex = k;
          }
        }
        img.drawPixel(diagram, i, j, baseStationList[minIndex].color);
      }
    }

    for (var pixel in baseStationList) {
      img.fillCircle(diagram, x: pixel.x, y: pixel.y, radius: 3, color: img.ColorFloat16.rgb(255, 255, 255));
    }
    return img.encodePng(diagram); 
  }
  Future<Uint8List> drawDiagram() async {
    try {
    final data = await Future.value(createDiagram());
    return data;
    } catch (e) {
      throw Exception('pizdec');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Voronoi Diagram'),
      ),
      body: Center(
        child: Column(
          children: [
            FutureBuilder(
              future: diagramImage,
              builder: (context, AsyncSnapshot<Uint8List> snapshot) {
                if (snapshot.hasData == false) {
                  return const Icon(Icons.image, );
                }
                if (snapshot.connectionState == ConnectionState.waiting) {
                  print('connection state waiting');
                  return const CircularProgressIndicator();
                }
                print('begin');
                return Image.memory(snapshot.data!);
              },
            ),
            MyTextField(
              hintText: 'Enter width', 
              textEditingController: textEditingControllerWidth,
            ),
            MyTextField(
              hintText: 'Enter heigth', 
              textEditingController: textEditingControllerHeight,
            ),
            MyTextField(
              hintText: 'Enter amount of stations', 
              textEditingController: textEditingControllerStations,
            ),
            ElevatedButton(
              onPressed: () {
               diagramImage = drawDiagram();
              },
              child: const Text('Create diagram'),
            )
          ],
        ),
      ),
    );
  }
}

我尝试使用 FutureBuilder,但不知何故,connectionState = ConnectionState.waiting 仅在一切准备就绪时才显示,因此我的应用程序只是口吃,直到所有计算完成。

flutter dart async-await statefulwidget
1个回答
0
投票

您正在函数内调用setState,但单击按钮时需要重建应用程序。

试试这个:

ElevatedButton(
    onPressed: () {
       setState(()=> diagramImage = drawDiagram());
    },
    child: const Text('Create diagram'),
)

现在您的数据流将是:

  • 给变量赋值
  • 更新状态(有一个函数正在运行,那么你的构建器状态将等待)
© www.soinside.com 2019 - 2024. All rights reserved.