Flutter——客户端
我们的后端现在已经启动并运行,接下来该创建flutter app了。
创建一个flutter 项目并添加以下依赖项:
- scoped_model: ^1.0.1
- flutter_socket_io: ^0.6.0
创建两个数据类: Message.dart 和 User.dart .
class Message{
final String text;
final String senderID;
final String receiverID;
Message(this.text,this.senderID,this.receiverID);
}
class User{
String name;
String chatID;
User(this.name,this.chatID);
}
然后创建ChatModel.dart, 里面所有socket 的逻辑和数据都会被保存。
ChatModel类不仅包含全部用户、当前用户和该用户朋友列表的虚拟数据,还包含了所有消息。ChatModel类中有三个类函数:
- init() :用来初始化所有变量以及初始化socket并向socket添加监听器。
- sendMessage() : 向服务器发送消息并将其添加到消息列表。
- getMessagesForChatID() : 从消息列表中提取与当前对话相关的消息。
下面让我们创建 AllChatsPage.dart。这将是显示所有用户的页面。
import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';
import './ChatPage.dart';
import './User.dart';
import './ChatModel.dart';
class AllChatsPage extends StatefulWidget {
@override
_AllChatsPageState createState() => _AllChatsPageState();
}
class _AllChatsPageState extends State<AllChatsPage> {
@override
void initState() {
super.initState();
ScopedModel.of<ChatModel>(context, rebuildOnChange: false).init();
}
void friendClicked(User friend) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return ChatPage(friend);
},
),
);
}
Widget buildAllChatList() {
return ScopedModelDescendant<ChatModel>(
builder: (context, child, model) {
return ListView.builder(
itemCount: model.friendList.length,
itemBuilder: (BuildContext context, int index) {
User friend = model.friendList[index];
return ListTile(
title: Text(friend.name),
onTap: () => friendClicked(friend),
);
},
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('All Chats'),
),
body: buildAllChatList(),
);
}
}
ChatModel中的 init()是在AllChatsPage的initState()中调用的,从而在启动时初始化我们的app。接着我们需创建ChatPage.dart用来显示消息。
import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';
import './User.dart';
import './Message.dart';
import './ChatModel.dart';
class ChatPage extends StatefulWidget {
final User friend;
ChatPage(this.friend);
@override
_ChatPageState createState() => _ChatPageState();
}
class _ChatPageState extends State<ChatPage> {
final TextEditingController textEditingController = TextEditingController();
Widget buildSingleMessage(Message message) {
return Container(
alignment: message.senderID == widget.friend.chatID
? Alignment.centerLeft
: Alignment.centerRight,
padding: EdgeInsets.all(10.0),
margin: EdgeInsets.all(10.0),
child: Text(message.text),
);
}
Widget buildChatList() {
return ScopedModelDescendant<ChatModel>(
builder: (context, child, model) {
List<Message> messages =
model.getMessagesForChatID(widget.friend.chatID);
return Container(
height: MediaQuery.of(context).size.height * 0.75,
child: ListView.builder(
itemCount: messages.length,
itemBuilder: (BuildContext context, int index) {
return buildSingleMessage(messages[index]);
},
),
);
},
);
}
Widget buildChatArea() {
return ScopedModelDescendant<ChatModel>(
builder: (context, child, model) {
return Container(
child: Row(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width * 0.8,
child: TextField(
controller: textEditingController,
),
),
SizedBox(width: 10.0),
FloatingActionButton(
onPressed: () {
model.sendMessage(
textEditingController.text, widget.friend.chatID);
textEditingController.text = '';
},
elevation: 0,
child: Icon(Icons.send),
),
],
),
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.friend.name),
),
body: ListView(
children: <Widget>[
buildChatList(),
buildChatArea(),
],
),
);
}
}
最后,打开main.dart,用以下代码替换现有的代码:
import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';
import './AllChatsPage.dart';
import './ChatModel.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ScopedModel(
model: ChatModel(),
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: AllChatsPage(),
),
);
}
}
怎样检测app是否能正常运行?
在一台设备上安装并运行app,然后打开ChatModel.dart,在 init()函数中初始化当前用户,示例如下:
currentUser=users[1]
在另一台设备上重建并运行该app。现在你就可以开启与别人聊天了。
下一步是什么?
为app构建一个超酷的UI。删除虚拟用户列表并将用户存储在某个数据库中。同时试着为特定用户实现显示在线状态。
快速提示:检查特定房间中的用户数。
如果你碰到任何问题,可以查看我的github repo :
当然了,如果你喜欢我这篇文章,别忘了收藏并点赞。如有任何疑问,评论区见。谢谢
原文作者 Ibtesam Ansari*
原文链接 Realtime Chat App - One-to-One using Flutter, Socket.io & Node.js