Flutter/Dart错误:参数类型'Future<File>'无法赋值给参数类型'File'。

17

我正在尝试使用Flutter和Firebase构建我的第一个移动应用程序。当我尝试显示和存储照片时,出现以下问题:

错误:参数类型“Future”无法分配给参数类型“File”。(argument_type_not_assignable at [whereassistant] lib/main.dart:85)

我可能需要进行一些强制转换,但我不知道如何正确地执行它。

这是我的Future文件声明:

Future<File> _imageFile;

我正在拍摄一张照片,该照片会显示在屏幕上:

    setState(() {
      _imageFile = ImagePicker.pickImage(source: source);
    });

但是当我尝试将照片发送到 Firebase 时,出现了错误:

    final StorageUploadTask uploadTask = ref.put(_imageFile);
    final Uri downloadUrl = (await uploadTask.future).downloadUrl;

这是我正在使用的类,基于一个代码示例:

class _MyHomePageState extends State<MyHomePage> {
  Future<File> _imageFile;

  void _onImageButtonPressed(ImageSource source) async {
    GoogleSignIn _googleSignIn = new GoogleSignIn();
    var account = await _googleSignIn.signIn();
    final GoogleSignInAuthentication googleAuth = await account.authentication;
    final FirebaseUser user = await _auth.signInWithGoogle(
      accessToken: googleAuth.accessToken,
      idToken: googleAuth.idToken,
    );
    assert(user.email != null);
    assert(user.displayName != null);
    assert(!user.isAnonymous);
    assert(await user.getIdToken() != null);

    final FirebaseUser currentUser = await _auth.currentUser();
    assert(user.uid == currentUser.uid);

    setState(() {
      _imageFile = ImagePicker.pickImage(source: source);
    });
    var random = new Random().nextInt(10000);
    var ref = FirebaseStorage.instance.ref().child('image_$random.jpg');
    final StorageUploadTask uploadTask = ref.put(_imageFile);
    final Uri downloadUrl = (await uploadTask.future).downloadUrl;
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: const Text('Where Assistant'),
      ),
      body: new Center(
        child: new FutureBuilder<File>(
          future: _imageFile,
          builder: (BuildContext context, AsyncSnapshot<File> snapshot) {
            debugPrint('test recup image');
            print(snapshot);

            if (snapshot.connectionState == ConnectionState.done &&
                snapshot.data != null) {
              return new Image.file(snapshot.data);
            } else if (snapshot.error != null) {
              return const Text('Error picking image.');
            } else {
              return const Text('No image so far.');
            }
          },
        ),
      ),
      floatingActionButton: new Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          new FloatingActionButton(
            onPressed: () => _onImageButtonPressed(ImageSource.gallery),
            tooltip: 'Pick an image from gallery',
            child: new Icon(Icons.photo_library),
          ),
          new Padding(
            padding: const EdgeInsets.only(top: 16.0),
            child: new FloatingActionButton(
              onPressed: () => _onImageButtonPressed(ImageSource.camera),
              tooltip: 'Take a Photo',
              child: new Icon(Icons.camera_alt),
            ),
          ),
        ],
      ),
    );
  }
}
6个回答

19

ref.put 要求传入一个File作为参数,而你传递的是一个Future<File>

你需要等待该 future 的结果才能发起调用。

你可以将你的代码更改为:

final StorageUploadTask uploadTask = ref.put(await _imageFile);
final Uri downloadUrl = (await uploadTask.future).downloadUrl;

或者将_imageFile改成File,而不是Future<File>


4
对于那些仍在寻找答案的人,似乎相同错误有不同的原因。在我的情况下,是因为我将一个文件作为参数传递给另一个函数时使用了不同的导入语句。在声明和定义时应该使用相同的文件(导入)。
例如,在Dart中不要像这样使用:
import 'GitRepoResponse.dart';
import 'GitRowItem.dart';

然后在另一个类中

import 'package:git_repo_flutter/GitRepoResponse.dart';
import 'package:git_repo_flutter/GitRowItem.dart';

因为

Dart中,只有当两个库使用相同的URI导入时,它们才是相同的。如果使用了两个不同的URI,即使它们解析为相同的文件,它们也被视为两个不同的库,并且文件中的类型会出现两次。

这里阅读更多


1
谢谢,您已经解决了问题:“import 'package:git_repo_flutter/..' 应该作为路径首选,特别是在测试文件中。” - Alessandro Ornano

3

来自 README.md 插件

  Future getImage() async {
    var image = await ImagePicker.pickImage(source: ImageSource.camera);

    setState(() {
      _image = image;
    });
  }

ImagePicker.pickImage() 会返回一个 Future。你可以像上面代码中所示那样使用 async/await 来获取 Future 中的值。


1

很可能是导入错误

import 'dart:io' as io; // use io.File even if File without io. works also

Future<io.File> method(){ // good, use as imported 
    File file = ...myfile // bad: it's not the imported type File
    return file; // FutureOr error
}

0
setState(() {
  _imageFile = ImagePicker.pickImage(source: source);
});

2
你不需要一个 await 吗? - Jeremy Caney
虽然此代码可能回答了问题,但提供有关它是如何解决问题的背景和/或原因会提高答案的长期价值。您可以在帮助中心找到有关编写良好答案的更多信息:https://stackoverflow.com/help/how-to-answer。祝好运。 - nima

0

要将 Future<File> 转换为 File,在函数前面添加 await,使其参数成为 Future 类型!

File file2 = await fixExifRotation(imageFile.path);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接