您如何称呼一个未来,然后将该返回值传递给另一个未来来运行?

时间:2019-04-23 06:14:19

标签: flutter future

我正在尝试用Android相机拍照,然后将该图片上传到Google Firebase Storage,在Storage上获取该图像的可下载URL,并在Firestore上更新用户的照片供稿。如果仅调用takeImage(),它将获取图像并将其成功上传到存储。如果我使用伪图像URL调用_uploadImage,它将正确更新提要。但是我无法将takeImage的结果作为参数传递给_uploadImage()。

void takeAndSave() async {
              url = await takeImage();
              _uploadImage(url);


          }


Future<String> takeImage() async {
    // open camera
    var image = await ImagePicker.pickImage(source: ImageSource.camera);

    // save image to temp storage
    final String fileName = "${Random().nextInt(10000)}.jpg";

    Directory directory = await getApplicationDocumentsDirectory(); // AppData folder path
    String appDocPath = directory.path;



    // copy image to path
    File savedImage = await image.copy('$appDocPath/' + fileName);

    // upload file to Firebase Storage
    final StorageReference ref = FirebaseStorage.instance.ref().child(fileName);
    final StorageUploadTask task = ref.putFile(savedImage);
    String downloadURL = await ref.getDownloadURL();
    url = downloadURL;
    //    _image = image;

    return downloadURL;
}



Future<void> _uploadImage(String url) async {
    final FirebaseUser user = await widget.auth.currentUser();
    String uid = user.uid;
    print('uid = ' + uid);
    print(url);
      // upload URL to Firebase Firestore Cloud Storage

      Firestore.instance.runTransaction((Transaction transaction) async {
        DocumentReference _newPhoto = Firestore.instance.collection('users').document(user.uid);

        await _newPhoto.collection('cards').add({"url" : url});

      });
  }

2 个答案:

答案 0 :(得分:0)

按照您的代码,它应该可以正常工作,但是您的takeImage()方法可能会返回一个异常。尝试捕获该异常,看看是否有帮助。

以下引用自https://www.dartlang.org/tutorials/language/futures#async-await

如果将来返回函数完成并出现错误,则您可能想捕获该错误。异步函数可以使用try-catch处理错误:

Future<String> takeImage() async {
  try {
    // Your code
  } catch (e) {
    // Handle error...
  }
}

答案 1 :(得分:0)

要链接将来的任务:表示如果我们有两个将来的任务,而第二个依赖于第一个响应的结果,则可以使用“ Future.wait()”。在下面的示例中,我创建了两个带有async关键字的方法,这些方法将从服务器获取数据,并且我想在第一个“ fetchPost()”响应之后执行“ fetchPostAgain()”方法,然后可以使用“ Future.wait()”

import 'dart:async';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter_app/models/Post.dart';
import 'package:http/http.dart' as http;

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
  }

  FetchFirstPost getFirstPost;
  String myString = "Loading...";

  void _takeImage() {
    Future.wait([fetchPost()]).then((FutureOr) => {
        fetchPostAgain()
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Example'),
        ),
        body: Center(
          child: Column(
            children: <Widget>[
              SingleChildScrollView(
                child: Text(myString),
              ),

              RaisedButton(
                    child: Text("Run Future"),
                    onPressed: _takeImage,
                          ),
              ],
          ),
          /*child: CallApiDemo(),*/
        ),
      ),
    );
  }



  Future<Post> fetchPost() async {
    final Completer completer = Completer();
    final response = await http.get('https://jsonplaceholder.typicode.com/posts/1');
    log('data: ' + response .statusCode.toString());
    if (response.statusCode == 200) {
      // If the call to the server was successful, parse the JSON
      setState(() {
        myString = response.body;
      });
      return postFromJson(response.body);
    } else {
      // If that call was not successful, throw an error.
      throw Exception('Failed to load post');
    }
  }

  Future<Post> fetchPostAgain() async{
    final response = await http.get('https://jsonplaceholder.typicode.com/posts/1');
    log('GOT SECOND RESPONSE');
    log('data: ' + response .statusCode.toString());
    if (response.statusCode == 200) {
      setState(() {
        myString = myString + "\n\n\nAGAIN\n\n\n" + response.body;
      });
      return postFromJson(response.body);
    } else {
      // If that call was not successful, throw an error.
      throw Exception('Failed to load post');
    }
  }

}