Flutter实战一Flutter聊天应用(八)
现在,我们将使用Firebase服务将聊天消息数据存储并同步到公用共享实时数据库上的云。我们需要使用 import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_database/ui/firebase_animated_list.dart';
在Firebase控制台中,更改Firebase实时数据库的安全规则,选择“Database > 规则”,规则如下所示。 {
"rules": { "messages": { ".read": true,".write": "auth != null && auth.provider == 'google'" } } }
上述规则允许公开的只读访问来自数据库的消息,以及用于将消息写入数据库的Google身份验证。此时,用户需要在发送消息之前登录,并且可以在不登录的情况下查看消息。 要加载用于显示的聊天消息并提交用户输入的消息,必须与Firebase实时数据库建立连接。首先,在我们的 class ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
//...
final reference = FirebaseDatabase.instance.reference().child('messages');
//...
}
应用程序现在可以使用此引用来读取和写入数据库中的特定位置,我们需要修改 class ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
//...
void _sendMessage({ String text }) {
reference.push().set({
'text': text,'senderName': googleSignIn.currentUser.displayName,'senderPhotoUrl': googleSignIn.currentUser.photoUrl,});
analytics.logEvent(name: 'send_message');
}
//...
}
要为每个聊天消息编写一个新行,需要调用由Firebase Database API定义的 当发送或接收消息时,项目早期版本的动画是从列表底部垂直滑动。UI的代码采用常规的以应用为中心的动画方法, 现在我们将使用一个专门的 首先将 class ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
//...
Widget build(BuildContext context) {
return new Scaffold(
//...
body: new Column(children: <Widget>[
new Flexible(
child: new FirebaseAnimatedList(
query: reference,sort: (a,b) => b.key.compareTo(a.key),padding: new EdgeInsets.all(8.0),reverse: true,itemBuilder: (_,DataSnapshot snapshot,Animation<double> animation) {
return new ChatMessage(
snapshot: snapshot,animation: animation
);
}
)
),new Divider(height: 1.0),new Container(
decoration: new BoxDecoration(
color: Theme.of(context).cardColor,),child: _buildTextComposer(),)
],);
}
//...
}
对于 最后,在 到现在,我们的应用程序一直在管理自己的 在 class ChatMessage extends StatelessWidget {
ChatMessage({this.snapshot,this.animation});
final DataSnapshot snapshot;
final Animation animation;
//...
}
同时,让我们将消息内容的字段从文本字符串更新为 class ChatMessage extends StatelessWidget {
//...
Widget build(BuildContext context) {
return new SizeTransition(
sizeFactor: new CurvedAnimation(
parent: animation,curve: Curves.eaSEOut
),//...
);
}
//...
}
从 class ChatScreenState extends State<ChatScreen> {
final TextEditingController _textController = new TextEditingController();
final reference = FirebaseDatabase.instance.reference().child('messages');
bool _isComposing = false;
//...
}
还要删除不再需要的 class ChatScreenState extends State<ChatScreen> {
//...
// @override
// void dispose() {
// for(ChatMessage message in _messages)
// message.animationController.dispose();
// super.dispose();
// }
//...
}
现在,我们可以调整使用用户配置文件信息的UI控件。以下控件需要从Firebase Database API获取以下信息:
而不是从 class ChatMessage extends StatelessWidget {
//...
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 Container(
margin: const EdgeInsets.only(right: 16.0),child: new GoogleUserCircleAvatar(snapshot.value['senderPhotoUrl']),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: new Text( snapshot.value['text'] ),)
]
)
]
)
)
);
}
//...
}
由于初始化状态对象需要重新启动应用程序,因此我们需要重新加载应用程序。 只使用单个设备,我们可以在Firebase控制台中的数据库下查看消息: 如果我们有两台设备连接到开发机器,那么我们则可以通过Firebase数据库发送消息并将其看到另一台设备的消息。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |