我正在尝试用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});
});
}
答案 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');
}
}
}