大佬教程收集整理的这篇文章主要介绍了Flutter实战一Flutter聊天应用(十七),大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
在正文开始之前,我们先组织一下数据,所有Firebase实时数据库的数据都被存储为Json对象。我们可以将该数据库视为云托管Json树,该数据库与sql数据库不同,没有任何表格或记录。当我们将数据添加至Json树时,它变为现有Json结构中的一个节点。
虽然Firebase实时数据库允许嵌套数据的深度多达32层,然而,当我们提取数据库中某个位置的数据时,也会检索所有子节点。另外,当我们向某用户授予数据库中某个节点的读写访问权时,也会将该节点下所有数据的访问权授予该用户。
在Firebase实时数据库中,数据结构最佳做法是平展数据结构,数据被拆分到不同路径(又称反规范化),可以根据需要通过不同调用有效地下载。即使列表含有成千上万条记录,也可单独提取和显示,从而确保UI 的及时响应和速度。
{
"users": { "1380001": { "email": "xingmi@163.com","name": "小明","password": "123456","@H_51_11@phone": "1380001" },"1380002": { "..": ".." },"1380003": { "..": ".." } },"chats": { "1380001": { "1380002": { "name": "小红","@H_51_11@phone": "1380002","messages": "13800011380002","lastmessage": "电路好像出问题了!","timestamp": 1459361875666,"activate": "true" },"1380003": { "name": "小刚","@H_51_11@phone": "1380003","messages": "13800011380003","lastmessage": "发现问题,有人把地线和火线接反","activate": "false" } },"messages": { "13800011380002": { "Ph6dARrtdEAUY5PDL2gt": { "name": "小红","message": "电路好像出问题了!" },"x415NpxFZM2CjibRMCcL": { "..": ".." } },"13800011380003": { "..": ".." },"13800031380002": { "..": ".." } } }
在@R_846_9616@程序中,用户个人资料位于“/users”路径中。现在有“/users/1380001”这个账户,它在“/chats/1380001”下检索所有的会话,再通过“/chats/1380001/messages”的值,在“/messages”中读取这个会话的所有聊天消息。
在上一篇文章中,我们实现了聊天列表屏幕的基本UI,在这一篇文本中,会具体实现添加会话的功能。具体实现则是当用户点击右下方的添加按钮时,会进入到添加会话屏幕,因此我们需要在/lib
目录下新建一个add_session.dart
文件,并添加以下代码。
import 'package:Flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import 'dart:async';
import 'prompt_wait.dart';
class AddSession extends StatefulWidget {
AddSession(this.myPhonE);
final String myPhone;
@override
State createState() => new _AddSessionState(myPhonE);
}
class _AddSessionState extends State<AddSession> {
_AddSessionState(this._myPhonE);
final String _myPhone;
@override
Widget build(BuildContext context) {
return new SimpleDialog(title: new Text("添加会话"),children: <Widget>[
new Text("这里用来放一些相关控件");
]);
}
}
在添加完add_session.dart
文件后,我们需要把聊天列表屏幕中的添加按钮与添加会话屏幕联系起来。修改group_chat_list.dart
文件,添加下面的代码,在用户点击按钮后,就会跳转到添加会话屏幕。这里传递了当前账户的手机号码给添加会话屏幕,使我们能访问对应账户的数据节点,以便添加或修改数据。
//...
import 'add_session.dart';
//...
class _GroupChatListState extends State<GroupChatList> {
//...
void _floaTingButtonCallBACk() {
showDialog<Null>(
context: context,barrierDismissible: false,child: new AddSession(phonE));
}
//...
Widget build(BuildContext context) {
//...
return new Scaffold(
//...
floaTingActionButton: new FloaTingActionButton(
BACkgroundColor: Colors.orange[800],elevation: 0.0,onPressed: _floaTingButtonCallBACk,child: new Icon(Icons.person_add)));
}
}
回到add_session.dart
文件中,在_AddSessionState
中添加一个_findUser
方法,用于查找用户是否存在,如果真实存在,则保存这个用户的手机号码和名称,用于给用户展示搜索结果。
class _AddSessionState extends State<AddSession> {
//...
final usersReference = FirebaseDatabase.instance.reference().child('users');
String _searchUsername = "";
String _searchPhone = "";
//...
Future<int> _findUser(String phonE) async {
return await usersReference
.child(phonE)
.once()
.then((DataSnapshot onvalue) {
if (onValue.value != null) {
_searchUsername = onValue.value["name"];
_searchPhone = onValue.value["phone"];
return 1;
} else {
return 0;
}
});
}
//...
}
我们还需要一个处理用户点击搜索按钮的事件,在_AddSessionState
中添加一个_handleFind
方法,用于判断用户输入的手机号码是否格式正确,确定没有格式问题,再调用上面的_findUser
方法,在数据库中查找该手机号码的账户,最后根据返回结果做对应操作。
class _AddSessionState extends State<AddSession> {
//...
final TextEdiTingController _phoneController = new TextEdiTingController();
//...
void _handleFind() {
FocusScope.of(context).requestFocus(new Focusnode());
if (_phoneController.text.isEmpty) {
showmessage(context,"手机号码不能为空!");
return;
} else if (_phoneController.text.trim() == widget.myPhonE) {
showmessage(context,"这是你的手机号码哦!");
return;
} else if (_phoneController.text.trim().length < 7 ||
_phoneController.text.trim().length > 12) {
showmessage(context,"手机号码的格式不正确!");
return;
}
showDialog<int>(
context: context,child: new ShowAwait(_findUser(_phoneController.text)))
.then((int onvalue) {
if (onValue == 0) {
showmessage(context,"该用户不存在!");
} else if (onValue == 1) {
setState(() {});
}
});
}
//...
}
现在我们在build
方法中添加手机号码输入框与搜索按钮,并将搜索按钮的点击事件设置成上面的_handleFind
方法。用户一但点击搜索按钮,首先会判断手机号码格式,然后再搜索是否有该用户并保存用户信息。
class _AddSessionState extends State<AddSession> {
//...
@override
Widget build(BuildContext context) {
return new SimpleDialog(title: new Text("添加会话"),children: <Widget>[
new Container(
margin: const EdgeInsets.symmetric(horizontal: 23.0),child: new Row(
children: <Widget>[
new Flexible(
child: new TextField(
controller: _phoneController,keyboardType: TexTinputType.phone,decoration:
new InputDecoration.collapsed(hintText: '点击此处输入手机号码'),)),new IconButton(
icon: new Icon(Icons.search),onPressed: () {
_handleFind();
}),],]);
}
}
上面的代码中,如果手机号码为真实账户,我们会保存账户信息,所以我们还需要将搜索到的账户信息展示给用户。在build
方法中添加一个展示用户信息的自定义控件。
class _AddSessionState extends State<AddSession> {
//...
@override
Widget build(BuildContext context) {
return new SimpleDialog(title: new Text("添加会话"),children: <Widget>[
//...
_searchUsername == ""
? new Text("")
: new Container(
margin: const EdgeInsets.symmetric(horizontal: 23.0),child: new Row(
children: <Widget>[
new CircleAvatar(
child: new Text(_searchUsername[0]),BACkgroundColor: Theme.of(context).buttonColor),new Flexible(
child: new column(
crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[
new Text(
" " + _searchUsername,textScaleFactor: 1.2,overflow: TextOverflow.ellipsis,),new Text(" " + _searchPhonE)
],))
],]);
}
}
我们在_AddSessionState
中添加一个_addSession
方法,用于在“/chats/$user/”下添加一个会话记录。在添加之前,还需要判断是否已经存在该记录,如果已经存在,说明已经添加过这个会话了,这时我们再判断该条记录的activate
值,如果是true就说明现在用户的聊天列表中有该条会话,否则说明用户已经删除该会话。
class _AddSessionState extends State<AddSession> {
//...
final chatsReference = FirebaseDatabase.instance.reference().child('chats');
//...
Future<int> _addSession() async {
return await chatsReference
.child('$_myPhone/$_searchPhone')
.once()
.then((DataSnapshot onvalue) {
if (onValue.value == null) {
chatsReference.child('$_myPhone/$_searchPhone').set({
"name": _searchUsername,"phone": _searchPhone,"messages": "$_myPhone$_searchPhone","lastmessage": "一起来聊天吧!","activate": "true"
});
return 1;
} else {
if (onValue.value["activate"] == truE) {
print("跳转到对应的聊天窗口");
return 0;
} else {
print("移除以前的记录,创建一条新记录");
return 2;
}
}
});
}
//...
}
现在添加一个处理用户点击添加按钮的事件,在_AddSessionState
中添加一个_handleAppend
方法,用于获取_addSession
方法的返回值,并做对应的操作。这里关于添加的流程还没有完成,我们会在完成聊天列表屏幕之后再写这些内容。
class _AddSessionState extends State<AddSession> {
//...
void _handleAppend() {
showDialog<int>(
context: context,barrierDismissible: false,child: new ShowAwait(_addSession())).then((int onvalue) {
if (onValue == 1) {
print("会话创建成功,返回到聊天列表屏幕");
}
});
}
//...
}
最后,我们在build
方法中增加一个取消按钮和添加按钮,其中添加按钮在用户没有搜索到好友之前为不可点击状态,搜索到好友之后才是可点击状态。
class _AddSessionState extends State<AddSession> {
//...
@override
Widget build(BuildContext context) {
return new SimpleDialog(title: new Text("添加会话"),children: <Widget>[
//...
new Container(
margin: const EdgeInsets.only(top: 18.0),child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: <Widget>[
new RaisedButton(
elevation: 0.0,onPressed: () {
Navigator.of(context).pop();
},colorBrightness: Brightness.dark,child: const Text('取消'),new RaisedButton(
elevation: 0.0,onPressed: _searchUsername == "" ? null : _handleAppend,colorBrightness:
_searchUsername == "" ? Brightness.light : Brightness.dark,child: const Text('添加'),))
]);
}
}
大家可以在GitHub上直接查看add_session.dart文件的代码。
以上是大佬教程为你收集整理的Flutter实战一Flutter聊天应用(十七)全部内容,希望文章能够帮你解决Flutter实战一Flutter聊天应用(十七)所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。