Flutter实战一Flutter聊天应用(九)
在这篇文章中,我们将允许用户在聊天消息中发送图像,从设备检索图像文件,并将文本和图像数据存储在Google云端存储Bucket中。由于我们使用Firebase云储存,应用程序将变得更加健壮和可扩展。它能够在上传和下载期间处理网络中断,安全地存储数据,并在用户群扩展时保持相同的性能。 要将数据(如文本和照片)从移动设备上传到云端,我们需要使用 import 'package:firebase_storage/firebase_storage.dart';
要访问存储在移动设备上的数据并在Flutter应用程序中使用它,我们需要Flutter的平台服务API和 import 'package:image_picker/image_picker.dart';
import 'dart:math';
import 'dart:io';
此时,我们的应用程序可以让用户发送和接收消息。现在,我们将在用户界面中添加一个按钮来撰写消息,使用户可以从应用访问设备的相机。然后我们将给UI处理二进制数据的能力。 需要注意的是,如果我们正在iOS设备上进行测试,那么需要添加一个设置,让图像选择器插件访问相机和设备上存储的图像。要启用访问,需要将以下条目添加到应用程序的 <dict>
<key>NSCameraUsageDescription</key>
<string>Share images with other chat users</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Share images with other chat users</string>
...
</dict>
用户需要一种访问存储在设备上的图像的方法,我们将在用于撰写聊天消息的UI旁边创建一个按钮。应用程序UI的这一部分由 class ChatScreenState extends State<ChatScreen> {
//...
Widget _buildTextComposer() {
return new IconTheme(
data: new IconThemeData(color: Theme.of(context).accentColor),child: new Container(
margin: const EdgeInsets.symmetric(horizontal: 8.0),child: new Row(
children: <Widget> [
new Container(
margin: new EdgeInsets.symmetric(horizontal: 4.0),child: new IconButton(
icon: new Icon(Icons.photo_camera),onPressed: (){}
),),new Flexible(
//...
),new Container(
//...
)
]
)
)
);
}
//...
}
在 现在修改相机按钮的 class ChatScreenState extends State<ChatScreen> {
//...
Widget _buildTextComposer() {
//...
child: new IconButton(
icon: new Icon(Icons.photo_camera),onPressed: () async {
await _ensureLoggedIn();
File imageFile = await ImagePicker.pickImage();
}
),//...
}
//...
}
在允许用户选择、上传和发送图像之前,确保通过执行私有 class ChatScreenState extends State<ChatScreen> {
//...
void _sendMessage({ String text,String imageUrl }) {
reference.push().set({
'text': text,'imageUrl': imageUrl,'senderName': googleSignIn.currentUser.displayName,'senderPhotoUrl': googleSignIn.currentUser.photoUrl,});
analytics.logEvent(name: 'send_message');
}
//...
}
创建一个用于将文件上传到Google Cloud Storage的实例变量,初始化它以获取对 class ChatScreenState extends State<ChatScreen> {
//...
Widget _buildTextComposer() {
//...
child: new IconButton(
icon: new Icon(Icons.photo_camera),onPressed: () async {
await _ensureLoggedIn();
File imageFile = await ImagePicker.pickImage();
int random = new Random().nextInt(100000);
StorageReference ref = FirebaseStorage.instance.ref().child("image_$random.jpg");
StorageUploadTask uploadTask = ref.put(imageFile);
Uri downloadUrl = (await uploadTask.future).downloadUrl;
}
),//...
}
//...
}
class ChatScreenState extends State<ChatScreen> {
//...
Widget _buildTextComposer() {
//...
child: new IconButton(
icon: new Icon(Icons.photo_camera),onPressed: () async {
await _ensureLoggedIn();
File imageFile = await ImagePicker.pickImage();
int random = new Random().nextInt(100000);
StorageReference ref = FirebaseStorage.instance.ref().child("image_$random.jpg");
StorageUploadTask uploadTask = ref.put(imageFile);
Uri downloadUrl = (await uploadTask.future).downloadUrl;
_sendMessage(imageUrl: downloadUrl.toString());
}
),//...
}
//...
}
这个URL用于应用程序UI从Google云端存储下载图像到本地,让发送人在聊天对话中查看他们发送的图像。发送或接收的每个聊天消息都需要能够显示图像和文本。接下来,我们将增强 class ChatMessage extends StatelessWidget {
//...
@override
Widget build(BuildContext context) {
return new SizeTransition(
//...
child: new Container(
margin: const EdgeInsets.symmetric(vertical: 10.0),child: new Row(
crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[
//...
new Column(
crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[
new Text(
snapshot.value['senderName'],style: Theme.of(context).textTheme.subhead),new Container(
margin: const EdgeInsets.only(top: 5.0),child: snapshot.value['imageUrl'] != null ?
new Image.network(
snapshot.value['imageUrl'],width: 250.0,):
new Text(snapshot.value['text']),)
]
)
]
)
)
);
}
}
在上面的代码中,如果数据库行的值字段是 因为我们在更改了iOS的 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |