【问题标题】:Getting 'Future<Image>' can't be assigned to a variable of type 'Image' in this Flutter/Dart code?在此 Flutter/Dart 代码中,无法将获取“Future<Image>”分配给“Image”类型的变量?
【发布时间】:2021-04-26 11:31:33
【问题描述】:

我正在尝试创建一个函数以在 Flutter (Dart) 中加载图像,但不知道如何使此代码正常工作。我得到:

“未来”类型的值不能分配给“图像”类型的变量。 尝试更改变量的类型,或将右侧类型转换为“图像”。

import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  ui.Image _backgroundImage;

  Future<ui.Image> loadImage(imageString) async {
    ByteData bd = await rootBundle.load(imageString);
    // ByteData bd = await rootBundle.load("graphics/bar-1920×1080.jpg");
    final Uint8List bytes = Uint8List.view(bd.buffer);
    final ui.Codec codec = await ui.instantiateImageCodec(bytes);
    final ui.Image image = (await codec.getNextFrame()).image;
    return image;
    // setState(() => imageStateVarible = image);
  }  

  @override
  Widget build(BuildContext context) {
    setState( () => {
      _backgroundImage = loadImage('imageNameString');  // <<== ISSUE: A value of type 'Future<Image>' can't be assigned to a variable of type 'Image'
    });

    return Scaffold(
      body: Center(
        child: Text('testing'),
      ),
    );
  }
}

【问题讨论】:

    标签: flutter dart dart-async


    【解决方案1】:

    试试这个。你的问题是:

    1. 不应在构建中调用诸如“下载图像”之类的内容。那应该是一个纯函数。
    2. 您的 loadImage 是异步的。因此我在 _asyncInit 中调用它。此外,您可能只想加载图像一次(而不是每次构建),所以我输入了 initState。
    import 'dart:typed_data';
    import 'dart:ui' as ui;
    
    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key}) : super(key: key);
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      ui.Image _backgroundImage;
    
      @override
      void initState() {
        super.initState();
        _asyncInit();
      }
    
      Future<void> _asyncInit() async {
        final image = await loadImage('imageNameString');
        setState(() {
          _backgroundImage = image;
        });
      }
    
      Future<ui.Image> loadImage(imageString) async {
        ByteData bd = await rootBundle.load(imageString);
        // ByteData bd = await rootBundle.load("graphics/bar-1920×1080.jpg");
        final Uint8List bytes = Uint8List.view(bd.buffer);
        final ui.Codec codec = await ui.instantiateImageCodec(bytes);
        final ui.Image image = (await codec.getNextFrame()).image;
        return image;
        // setState(() => imageStateVarible = image);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: _backgroundImage != null ? YourWidget(_backgroundImage) : Text('you are loading that image'),
          ),
        );
      }
    }
    
    

    编辑

    如果你想要一个图像数组:

    import 'dart:typed_data';
    import 'dart:ui' as ui;
    
    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key}) : super(key: key);
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      List<ui.Image> _backgroundImages;
    
      @override
      void initState() {
        super.initState();
        _asyncInit();
      }
    
      Future<void> _asyncInit() async {
        final imageNames = ['firstimage', 'secondimage', 'thirdimage'];
        // NOTE by doing this, your images are loaded **simutanously** instead of **waiting for one to finish before starting the next**
        final futures = [for (final name in imageNames) loadImage(name)];
        final images = await Future.wait(futures);
        setState(() {
          _backgroundImages = images;
        });
      }
    
      Future<ui.Image> loadImage(imageString) async {
        ByteData bd = await rootBundle.load(imageString);
        // ByteData bd = await rootBundle.load("graphics/bar-1920×1080.jpg");
        final Uint8List bytes = Uint8List.view(bd.buffer);
        final ui.Codec codec = await ui.instantiateImageCodec(bytes);
        final ui.Image image = (await codec.getNextFrame()).image;
        return image;
        // setState(() => imageStateVarible = image);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: _backgroundImages != null ? YourWidget(_backgroundImages) : Text('you are loading that image'),
          ),
        );
      }
    }
    

    【讨论】:

    • 谢谢 - 这解决了问题 - 实际上,如果我最终想要循环通过一组图像进行预加载,_asyncInit() 函数需要是什么样的? (或者我应该提出单独的问题?)
    • 很棒的东西谢谢你——希望这个异步的东西很快就会点击。 :)
    • 您是否碰巧知道您是否有一个状态数组,当您更新数组时会触发数组中所有项的更新(重绘),还是仅触发已更改的项?
    • @Greg 不,nothing 会自动发生。实际上,魔法发生在setState - setState 的意思是“将此 statefulwidget 标记为需要重建”。您可以创建另一个问题,以便其他有此问题的人也可以受益,我可以详细说明一下,例如,挖掘源代码:)
    • 顺便说一句 - 刚刚创建了新问题:stackoverflow.com/questions/65838077/…
    猜你喜欢
    • 1970-01-01
    • 2020-08-23
    • 2020-01-21
    • 2020-01-23
    • 2021-12-31
    • 2021-12-16
    • 2022-01-15
    • 2013-01-10
    • 2021-01-29
    相关资源
    最近更新 更多