flutter / dart error: The argument type 'Future<File>' can't be assigned to the parameter type 'File'

flutter / dart error: The argument type 'Future<File>' can't be assigned to the parameter type 'File'

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

error: The argument type 'Future' can't be assigned to the parameter type 'File'. (argument_type_not_assignable at [whereassistant] lib/main.dart:85)

我可能应该做一些转换,但我不明白如何正确地做。

这是我的未来文件声明:

Future<File> _imageFile;

我正在拍照并显示在屏幕上:

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

但是我在尝试将照片发送到 Firebase 时遇到错误:

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

这是我根据代码示例使用的 class:

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

来自插件README.md

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

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

ImagePicker.pickImage()returns一个Future。您可以使用 async/await ,如上面的代码所示,从 Future.

中获取值

ref.put 要求 File 作为参数。你传递的是 Future<File>

您需要等待那个未来的结果才能做出决定。

您可以将代码更改为

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

或将_imageFile改为File而不是Future<File>

对于那些仍在寻找答案的人来说,似乎同一个错误有不同的原因。在我的例子中,这是我作为参数传递给不同函数的文件的不同导入语句。在声明和定义的情况下,它应该是相同的文件(导入)。

例如,不要在 dart 中这样使用

import 'GitRepoResponse.dart';
import 'GitRowItem.dart';

然后在另一个 class

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

因为

In Dart, two libraries are the same if, and only if, they are imported using the same URI. If two different URIs are used, even if they resolve to the same file, they will be considered to be two different libraries and the types within the file will occur twice

阅读更多here

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

File file2 = await fixExifRotation(imageFile.path);
setState(() {
  _imageFile = ImagePicker.pickImage(source: source);
});