Getting 'Future<Image>' can't be assigned to a variable of type 'Image' in this Flutter/Dart code?

牧云@^-^@ 提交于 2021-01-29 09:25:27

问题


I'm trying create a function to load images in Flutter (Dart) but not sure how to get this code working. I'm getting:

A value of type 'Future' can't be assigned to a variable of type 'Image'. Try changing the type of the variable, or casting the right-hand type to '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> {
  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'),
      ),
    );
  }
}

回答1:


Try this. Your problem is:

  1. should not call things like "download an image" inside build. That should be a pure function.
  2. Your loadImage is async. Thus I call it inside the _asyncInit. In addition, you may only want to load the image once (instead of every build), so I put in 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'),
      ),
    );
  }
}

EDIT:

If you want an array of images:

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


来源:https://stackoverflow.com/questions/65837703/getting-futureimage-cant-be-assigned-to-a-variable-of-type-image-in-this

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!