Flutter聊天数据持久化插件stream_chat_persistence的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter聊天数据持久化插件stream_chat_persistence的使用

官方Stream Chat持久化客户端

官方提供的Stream Chat持久化客户端,用于构建聊天应用程序。该包提供了从本地获取和保存聊天数据的功能。Stream Chat Persistence 使用 Moor 作为磁盘缓存。

Platform

快速链接

添加依赖

pubspec.yaml 文件中添加如下内容,并确保使用最新版本:

dependencies:
  stream_chat_persistence: ^latest_version

然后运行 flutter packages get

使用方法

  1. 创建一个新的 StreamChatPersistenceClient 实例,提供 logLevelconnectionMode 参数。

    final chatPersistentClient = StreamChatPersistenceClient(
      logLevel: Level.INFO,
      connectionMode: ConnectionMode.regular,
    );
    
  2. 将实例传递给官方的 Stream 聊天客户端。

    final client = StreamChatClient(
      apiKey ?? kDefaultStreamApiKey,
      logLevel: Level.INFO,
    )..chatPersistenceClient = chatPersistentClient;
    

Flutter Web

由于 Moor web(用于离线存储),你需要包含 sql.js 库:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script defer src="sql-wasm.js"></script>
    <script defer src="main.dart.js" type="application/javascript"></script>
</head>
<body></body>
</html>

你可以从 这里 获取最新版本的 sql-wasm.jssql-wasm.wasm 并复制到你的 /web 文件夹中。

示例代码

以下是一个完整的示例demo:

import 'package:flutter/material.dart';
import 'package:stream_chat/stream_chat.dart';
import 'package:stream_chat_persistence/stream_chat_persistence.dart';

Future<void> main() async {
  /// 创建一个新的 StreamChatClient 实例,传递从项目仪表板获得的apikey。
  final client = StreamChatClient('your_api_key');

  WidgetsFlutterBinding.ensureInitialized();

  /// 设置 chatPersistenceClient 以支持离线功能
  client.chatPersistenceClient = StreamChatPersistenceClient(
    logLevel: Level.INFO,
    connectionMode: ConnectionMode.background,
  );

  /// 设置当前用户。在生产环境中,这应该通过后端使用我们的服务器 SDK 生成用户令牌。
  await client.connectUser(
    User(
      id: 'your_user_id',
      image: 'your_image_url',
    ),
    'your_user_token', // 请参阅:https://getstream.io/chat/docs/ios_user_setup_and_tokens/
  );

  /// 创建一个类型为 `messaging` 的通道,ID 为 `godevs`。
  final channel = client.channel('messaging', id: 'godevs');

  /// `.watch()` 用于创建并监听通道更新。如果通道已存在,则仅监听新事件。
  await channel.watch();

  runApp(
    StreamExample(
      client: client,
      channel: channel,
    ),
  );
}

/// 使用 Stream 的低级 Dart 客户端的示例。
class StreamExample extends StatelessWidget {
  const StreamExample({
    super.key,
    required this.client,
    required this.channel,
  });

  final StreamChatClient client;
  final Channel channel;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Stream Chat Dart Example',
      home: HomeScreen(channel: channel),
    );
  }
}

/// 应用程序的主要屏幕。布局由包含通道名称的 [AppBar] 和显示最近消息的 [MessageView] 组成。
class HomeScreen extends StatelessWidget {
  const HomeScreen({
    super.key,
    required this.channel,
  });

  final Channel channel;

  @override
  Widget build(BuildContext context) {
    final messages = channel.state!.channelStateStream;
    return Scaffold(
      appBar: AppBar(
        title: Text('Channel: ${channel.id}'),
      ),
      body: SafeArea(
        child: StreamBuilder<ChannelState?>(
          stream: messages,
          builder: (
            BuildContext context,
            AsyncSnapshot<ChannelState?> snapshot,
          ) {
            if (snapshot.hasData && snapshot.data != null) {
              final _messages = snapshot.data!.messages ?? [];
              return MessageView(
                messages: _messages.reversed.toList(),
                channel: channel,
              );
            } else if (snapshot.hasError) {
              return const Center(
                child: Text(
                  'There was an error loading messages. Please see logs.',
                ),
              );
            }
            return const Center(
              child: SizedBox(
                width: 100,
                height: 100,
                child: CircularProgressIndicator(),
              ),
            );
          },
        ),
      ),
    );
  }
}

/// 显示最近消息列表和发送新消息的 [TextField] 的UI。
class MessageView extends StatefulWidget {
  const MessageView({
    super.key,
    required this.messages,
    required this.channel,
  });

  final List<Message> messages;
  final Channel channel;

  @override
  _MessageViewState createState() => _MessageViewState();
}

class _MessageViewState extends State<MessageView> {
  late final TextEditingController _controller;
  late final ScrollController _scrollController;

  List<Message> get _messages => widget.messages;

  @override
  void initState() {
    super.initState();
    _controller = TextEditingController();
    _scrollController = ScrollController();
  }

  @override
  void dispose() {
    _controller.dispose();
    _scrollController.dispose();
    super.dispose();
  }

  /// 发送新消息时滚动列表视图的方法。
  void _updateList() {
    _scrollController.animateTo(
      0,
      duration: const Duration(milliseconds: 200),
      curve: Curves.easeOut,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
          child: ListView.builder(
            controller: _scrollController,
            itemCount: _messages.length,
            reverse: true,
            itemBuilder: (BuildContext context, int index) {
              final item = _messages[index];
              if (item.user?.id == widget.channel.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 ?? ''),
                  ),
                );
              }
            },
          ),
        ),
        Padding(
          padding: const EdgeInsets.all(8),
          child: Row(
            children: [
              Expanded(
                child: TextField(
                  controller: _controller,
                  decoration: const InputDecoration(
                    hintText: 'Enter your message',
                  ),
                ),
              ),
              Material(
                type: MaterialType.circle,
                color: Colors.blue,
                clipBehavior: Clip.hardEdge,
                child: InkWell(
                  onTap: () async {
                    if (_controller.value.text.isNotEmpty) {
                      await widget.channel.sendMessage(
                        Message(text: _controller.value.text),
                      );
                      _controller.clear();
                      _updateList();
                    }
                  },
                  child: const Padding(
                    padding: EdgeInsets.all(8),
                    child: Center(
                      child: Icon(
                        Icons.send,
                        color: Colors.white,
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }
}

/// 快捷扩展,用于快速检索 StreamChatClient 中的当前用户 ID。
extension on StreamChatClient {
  String get uid => state.currentUser!.id;
}

以上代码展示了如何使用 stream_chat_persistence 插件来实现聊天应用中的数据持久化功能。


更多关于Flutter聊天数据持久化插件stream_chat_persistence的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter聊天数据持久化插件stream_chat_persistence的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter应用中使用stream_chat_persistence插件来实现聊天数据持久化的代码案例。这个插件主要用于将Stream Chat的数据缓存到本地存储中,以便在没有网络连接的情况下也能访问最近的聊天数据。

首先,确保你的Flutter项目中已经添加了stream_chatstream_chat_persistence依赖。在pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  stream_chat: ^x.y.z  # 请替换为最新版本号
  stream_chat_persistence: ^x.y.z  # 请替换为最新版本号

然后运行flutter pub get来安装这些依赖。

接下来,配置Stream Chat客户端并启用持久化功能。以下是一个完整的示例代码:

import 'package:flutter/material.dart';
import 'package:stream_chat/stream_chat.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'package:stream_chat_persistence/stream_chat_persistence.dart';
import 'package:path_provider/path_provider.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 获取应用文档目录
  final Directory appDocDir = await getApplicationDocumentsDirectory();
  final String storagePath = appDocDir.path;

  // 配置Stream Chat客户端
  final client = StreamChatClient(
    apiKey: 'your-api-key', // 替换为你的Stream API密钥
    appId: 'your-app-id',   // 替换为你的Stream应用ID
  );

  // 配置持久化存储
  final persistence = await StreamChatPersistence.create(
    client: client,
    storagePath: storagePath,
  );

  // 启用持久化功能
  client.persistenceManager = persistence;

  // 初始化Stream Chat用户(假设用户已经登录)
  final user = User(
    id: 'user-id',
    name: 'User Name',
    imageURL: 'https://example.com/image.png',
  );
  await client.connectUser(user, token: 'user-token'); // 替换为用户的认证token

  runApp(MyApp(client: client));
}

class MyApp extends StatelessWidget {
  final StreamChatClient client;

  MyApp({required this.client});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Stream Chat Example'),
        ),
        body: ChatScreen(
          chatClient: client,
          channelId: 'channel-id', // 替换为你想查看的频道ID
        ),
      ),
    );
  }
}

在这个示例中,我们完成了以下步骤:

  1. 获取应用文档目录的路径,用于存储持久化数据。
  2. 创建并配置StreamChatClient实例。
  3. 使用StreamChatPersistence.create方法创建一个持久化存储实例,并将其赋值给client.persistenceManager
  4. 初始化并连接用户。
  5. 使用ChatScreen组件显示聊天界面,传入配置好的StreamChatClient实例和频道ID。

请确保你已经替换了示例代码中的API密钥、应用ID、用户ID、用户token和频道ID为实际的值。

这个配置完成后,你的Flutter应用将能够自动将聊天数据持久化到本地存储中,并在没有网络连接时仍能访问最近的聊天记录。

回到顶部