Flutter即时通讯插件stream_chat_flutter_core的使用
Flutter即时通讯插件stream_chat_flutter_core的使用
概述
stream_chat_flutter_core
是 Stream Chat 的官方 Flutter 核心组件,用于构建聊天应用程序。该插件提供了业务逻辑层的支持,允许开发者更灵活地自定义聊天应用的功能和界面。
快速链接
- 注册 获取 Stream Chat API Key
- Flutter 聊天教程
- Chat UI Kit
- 核心文档
版本迁移指南
- 从 V3 升级到 V4,请参考V4 迁移指南
示例代码
以下是一个完整的示例代码,展示了如何使用 stream_chat_flutter_core
构建一个简单的聊天应用。
1. 添加依赖
在 pubspec.yaml
文件中添加 stream_chat_flutter_core
依赖:
dependencies:
stream_chat_flutter_core: ^latest_version
然后运行 flutter packages get
来安装依赖。
2. 初始化客户端并连接用户
在 main.dart
文件中初始化 StreamChatClient
并连接用户:
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
Future<void> main() async {
// 创建 StreamChatClient 实例,并传入你的 API Key
final client = StreamChatClient('YOUR_API_KEY');
// 设置当前用户。生产环境中应通过后端生成用户令牌。
await client.connectUser(
User(
id: 'user-id',
image: 'https://example.com/user-image.jpg',
),
'YOUR_USER_TOKEN', // 用户令牌
);
runApp(
StreamExample(
client: client,
),
);
}
class StreamExample extends StatelessWidget {
const StreamExample({
Key? key,
required this.client,
}) : super(key: key);
final StreamChatClient client;
@override
Widget build(BuildContext context) => MaterialApp(
title: 'Stream Chat Core Example',
home: HomeScreen(),
builder: (context, child) => StreamChatCore(
client: client,
child: child!,
),
);
}
3. 显示频道列表
创建一个 HomeScreen
页面来显示用户参与的频道列表:
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
late final channelListController = StreamChannelListController(
client: StreamChatCore.of(context).client,
filter: Filter.and([
Filter.equal('type', 'messaging'),
Filter.in_(
'members',
[StreamChatCore.of(context).currentUser!.id],
),
]),
);
@override
void initState() {
channelListController.doInitialLoad();
super.initState();
}
@override
void dispose() {
channelListController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Channels'),
),
body: PagedValueListenableBuilder<int, Channel>(
valueListenable: channelListController,
builder: (context, value, child) {
return value.when(
(channels, nextPageKey, error) => LazyLoadScrollView(
onEndOfPage: () async {
if (nextPageKey != null) {
channelListController.loadMore(nextPageKey);
}
},
child: ListView.builder(
itemCount: (nextPageKey != null || error != null)
? channels.length + 1
: channels.length,
itemBuilder: (BuildContext context, int index) {
if (index == channels.length) {
if (error != null) {
return TextButton(
onPressed: () {
channelListController.retry();
},
child: Text(error.message),
);
}
return const CircularProgressIndicator();
}
final _item = channels[index];
return ListTile(
title: Text(_item.name ?? ''),
subtitle: StreamBuilder<Message?>(
stream: _item.state!.lastMessageStream,
initialData: _item.state!.lastMessage,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.text!);
}
return const SizedBox();
},
),
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => StreamChannel(
channel: _item,
child: const MessageScreen(),
),
),
);
},
);
},
),
),
loading: () => const Center(
child: SizedBox(
height: 100,
width: 100,
child: CircularProgressIndicator(),
),
),
error: (e) => Center(
child: Text(
'Oh no, something went wrong. Please check your config. $e',
),
),
);
},
),
);
}
4. 显示消息列表
创建一个 MessageScreen
页面来显示选定频道的消息列表:
class MessageScreen extends StatefulWidget {
const MessageScreen({Key? key}) : super(key: key);
@override
_MessageScreenState createState() => _MessageScreenState();
}
class _MessageScreenState extends State<MessageScreen> {
final StreamMessageInputController messageInputController =
StreamMessageInputController();
late final ScrollController _scrollController;
final messageListController = MessageListController();
@override
void initState() {
super.initState();
_scrollController = ScrollController();
}
@override
void dispose() {
messageInputController.dispose();
_scrollController.dispose();
super.dispose();
}
void _updateList() {
_scrollController.animateTo(
0,
duration: const Duration(milliseconds: 200),
curve: Curves.easeOut,
);
}
@override
Widget build(BuildContext context) {
final channel = StreamChannel.of(context).channel;
return Scaffold(
appBar: AppBar(
title: StreamBuilder<Iterable<User>>(
initialData: channel.state?.typingEvents.keys,
stream: channel.state?.typingEventsStream.map((it) => it.keys),
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
return Text('${snapshot.data!.first.name} is typing...');
}
return const SizedBox();
},
),
),
body: SafeArea(
child: Column(
children: [
Expanded(
child: LazyLoadScrollView(
onEndOfPage: () async {
messageListController.paginateData!();
},
child: MessageListCore(
messageListController: messageListController,
emptyBuilder: (BuildContext context) => const Center(
child: Text('Nothing here yet'),
),
loadingBuilder: (BuildContext context) => const Center(
child: SizedBox(
height: 100,
width: 100,
child: CircularProgressIndicator(),
),
),
messageListBuilder: (
BuildContext context,
List<Message> messages,
) =>
ListView.builder(
controller: _scrollController,
itemCount: messages.length,
reverse: true,
itemBuilder: (BuildContext context, int index) {
final item = messages[index];
final client = StreamChatCore.of(context).client;
if (item.user!.id == client.uid) {
return Align(
alignment: Alignment.centerRight,
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(item.text!),
),
);
} else {
return Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(item.text!),
),
);
}
},
),
errorBuilder: (BuildContext context, error) {
print(error.toString());
return const Center(
child: SizedBox(
height: 100,
width: 100,
child: Text('Oh no, an error occurred. Please see logs.'),
),
);
},
),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: Row(
children: [
Expanded(
child: TextField(
controller: messageInputController.textFieldController,
decoration: const InputDecoration(
hintText: 'Enter your message',
),
),
),
Material(
type: MaterialType.circle,
color: Colors.blue,
clipBehavior: Clip.hardEdge,
child: InkWell(
onTap: () async {
if (messageInputController.text.isNotEmpty) {
await channel.sendMessage(
messageInputController.message,
);
messageInputController.clear();
if (mounted) {
_updateList();
}
}
},
child: const Padding(
padding: EdgeInsets.all(8),
child: Center(
child: Icon(
Icons.send,
color: Colors.white,
),
),
),
),
),
],
),
),
],
),
),
);
}
}
5. 扩展功能
你可以通过扩展 StreamChatClient
来添加更多功能:
extension on StreamChatClient {
String get uid => state.currentUser!.id;
}
结论
通过以上步骤,你已经成功集成了 stream_chat_flutter_core
插件,并实现了一个简单的聊天应用。你可以根据需求进一步自定义和扩展这个应用。更多详细信息可以参考官方文档。
更多关于Flutter即时通讯插件stream_chat_flutter_core的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter即时通讯插件stream_chat_flutter_core的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用stream_chat_flutter_core
插件来实现即时通讯功能的代码示例。这个示例将涵盖基本的设置、用户认证、频道创建和消息发送等核心功能。
1. 添加依赖
首先,在pubspec.yaml
文件中添加stream_chat_flutter_core
及其依赖项:
dependencies:
flutter:
sdk: flutter
stream_chat_flutter_core: ^latest_version # 请替换为最新版本号
stream_chat_flutter: ^latest_version # UI组件库,如果需要的话
2. 配置Stream Chat
在你的Flutter应用的入口文件(通常是main.dart
)中,配置Stream Chat:
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化Stream Chat客户端
final client = StreamChatClient(
apiKey: 'your_api_key', // 替换为你的Stream API Key
appId: 'your_app_id', // 替换为你的Stream App ID
);
// 设置全局客户端实例(可选,但推荐)
StreamChat.of(context).client = client;
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ChatScreen(),
);
}
}
3. 用户认证
假设你已经有一个用户系统,可以使用Stream Chat的connectUser
方法进行用户认证:
class ChatScreen extends StatefulWidget {
@override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
late StreamChatClient client;
@override
void initState() {
super.initState();
client = StreamChat.of(context).client!;
// 假设用户已经登录,这里使用模拟数据
final user = User(
id: 'user-123',
name: 'John Doe',
imageURL: 'https://example.com/avatar.png',
);
client.connectUser(user, token: 'user-token-123').then((session) {
// 用户连接成功后的逻辑
print('User connected: ${session.user.id}');
}).catchError((error) {
// 处理错误
print('Error connecting user: $error');
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Chat Screen')),
body: Center(child: Text('Connecting user...')), // 暂时显示连接中的状态
);
}
}
4. 创建频道并发送消息
在成功连接用户后,可以创建一个频道并向其中发送消息:
class _ChatScreenState extends State<ChatScreen> {
late StreamChatClient client;
late Channel? channel;
@override
void initState() {
super.initState();
client = StreamChat.of(context).client!;
// 用户连接逻辑(同上)
client.connectUser(User(
id: 'user-123',
name: 'John Doe',
imageURL: 'https://example.com/avatar.png',
), token: 'user-token-123').then((session) {
// 创建频道
channel = client.channel('messaging', 'channel-id-123',
extraData: {'name': 'General Chat'});
// 发送消息
channel!.sendMessage(
Message(
text: 'Hello, this is a test message!',
user: session.user,
),
).then((message) {
// 消息发送成功后的逻辑
print('Message sent: ${message.id}');
}).catchError((error) {
// 处理错误
print('Error sending message: $error');
});
}).catchError((error) {
// 处理错误
print('Error connecting user: $error');
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Chat Screen')),
body: Center(
child: channel != null
? Text('Channel created and message sent!')
: Text('Connecting user and creating channel...'),
),
);
}
}
5. 显示聊天界面(可选)
如果你希望显示一个完整的聊天界面,可以使用stream_chat_flutter
包提供的UI组件。这里是一个简单的例子:
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
class ChatScreen extends StatefulWidget {
@override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
late StreamChatClient client;
late Channel? channel;
@override
void initState() {
super.initState();
client = StreamChat.of(context).client!;
// 用户连接和频道创建逻辑(同上)
// ...
// 假设这些步骤已经完成,直接跳转到聊天界面
Future.wait([userConnectionFuture, channelCreationFuture]).then((_) {
// 使用Stream Chat的UI组件显示聊天界面
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChatScreenWidget(
channel: channel!,
),
),
);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Loading Chat...')),
);
}
}
class ChatScreenWidget extends StatelessWidget {
final Channel channel;
ChatScreenWidget({required this.channel});
@override
Widget build(BuildContext context) {
return ChatScreen(
channel: channel,
messagesController: MessagesController(
channel: channel,
),
);
}
}
请注意,上述代码中的userConnectionFuture
和channelCreationFuture
是模拟的Future对象,你需要根据实际情况替换为实际的Future逻辑。
以上代码提供了一个基本的框架,展示了如何在Flutter应用中使用stream_chat_flutter_core
插件进行即时通讯。根据具体需求,你可能需要调整和完善这些代码。