Flutter事件流监听插件eventsource的使用

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

Flutter事件流监听插件eventsource的使用

eventsource 是一个用于在Flutter中实现EventSource或服务器发送事件(Server-Sent Events, SSE)的库。它提供了客户端和服务器端的功能,遵循 HTML规范 中描述的接口。

客户端使用

创建一个新的 EventSource 客户端非常简单,只需调用 EventSource.connect 方法即可。该方法内部使用了 http 包,因此只要 http 包可以工作的地方,eventsource 也可以工作。浏览器环境下的使用略有不同。

import 'package:eventsource/eventsource.dart';
import 'package:http/browser_client.dart'; // 仅在浏览器中使用

void main() async {
  try {
    // 在非浏览器环境中使用
    EventSource eventSource = await EventSource.connect("http://example.com/events");

    // 在浏览器环境中使用
    EventSource eventSource = await EventSource.connect(
      "http://example.com/events",
      client: http.BrowserClient(),
    );

    // 监听事件
    eventSource.listen((EventSourceMessage event) {
      print('Received event: ${event.data}');
    });

    // 监听错误
    eventSource.onError.listen((error) {
      print('Error: $error');
    });

    // 监听连接关闭
    eventSource.onDone.listen((_) {
      print('Connection closed');
    });

  } catch (e) {
    print('Failed to connect: $e');
  }
}

服务器端使用

对于服务器端的实现,推荐使用 shelf_eventsource 包来提供 Server-Sent Events 服务。shelf_eventsource 提供了一个 EventSourcePublisher,用于管理订阅、通道和编码。关于更多详细信息,请参考 shelf_eventsource 的文档。

此外,eventsource 库还为 dart:ioHttpServer 提供了一个服务器端实现,位于 io_server.dart 文件中。然而,该实现存在一些数据刷新的问题,尚未完全解决,因此建议使用 shelf 作为替代方案。

完整示例 Demo

以下是一个完整的 Flutter 示例,展示了如何在客户端使用 eventsource 插件来监听服务器发送的事件:

import 'package:flutter/material.dart';
import 'package:eventsource/eventsource.dart';
import 'package:http/browser_client.dart'; // 仅在浏览器中使用

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'EventSource Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: EventStreamPage(),
    );
  }
}

class EventStreamPage extends StatefulWidget {
  [@override](/user/override)
  _EventStreamPageState createState() => _EventStreamPageState();
}

class _EventStreamPageState extends State<EventStreamPage> {
  final List<String> _events = [];
  EventSource? _eventSource;

  [@override](/user/override)
  void initState() {
    super.initState();
    _connectToEventSource();
  }

  Future<void> _connectToEventSource() async {
    try {
      // 在非浏览器环境中使用
      _eventSource = await EventSource.connect("http://example.com/events");

      // 在浏览器环境中使用
      // _eventSource = await EventSource.connect(
      //   "http://example.com/events",
      //   client: http.BrowserClient(),
      // );

      // 监听事件
      _eventSource!.listen((EventSourceMessage event) {
        setState(() {
          _events.add(event.data);
        });
      });

      // 监听错误
      _eventSource!.onError.listen((error) {
        print('Error: $error');
      });

      // 监听连接关闭
      _eventSource!.onDone.listen((_) {
        print('Connection closed');
      });

    } catch (e) {
      print('Failed to connect: $e');
    }
  }

  [@override](/user/override)
  void dispose() {
    _eventSource?.close(); // 关闭事件源连接
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('EventSource Demo'),
      ),
      body: ListView.builder(
        itemCount: _events.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(_events[index]),
          );
        },
      ),
    );
  }
}

更多关于Flutter事件流监听插件eventsource的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter事件流监听插件eventsource的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter中使用eventsource插件来监听事件流的示例代码。这个插件允许你从支持Server-Sent Events (SSE)的服务器接收实时事件流。

首先,确保你已经在pubspec.yaml文件中添加了eventsource依赖:

dependencies:
  flutter:
    sdk: flutter
  eventsource: ^2.0.0 # 请检查最新版本号

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

接下来是一个完整的Flutter应用示例,展示了如何使用eventsource插件来监听事件流:

import 'package:flutter/material.dart';
import 'package:eventsource/eventsource.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'EventSource Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final TextEditingController _controller = TextEditingController();
  EventSource? _eventSource;
  final List<String> _events = [];

  @override
  void initState() {
    super.initState();
    // 可以在这里设置一个初始URL来监听事件流
    // 例如:_startEventListening('https://example.com/events');
  }

  void _startEventListening(String url) {
    _eventSource?.close(); // 如果已经有一个事件源在运行,先关闭它

    _eventSource = EventSource(url);

    _eventSource!.onMessage.listen((event) {
      setState(() {
        _events.add('Received message: ${event.data}');
      });
    });

    _eventSource!.onError.listen((error) {
      setState(() {
        _events.add('Error: ${error.message}');
      });
      _eventSource!.close(); // 发生错误时关闭事件源
    });

    _eventSource!.onOpen.listen((_) {
      setState(() {
        _events.add('Connection opened');
      });
    });

    _eventSource!.onClose.listen((_) {
      setState(() {
        _events.add('Connection closed');
      });
    });
  }

  @override
  void dispose() {
    _eventSource?.close(); // 在组件销毁时关闭事件源
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('EventSource Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            TextField(
              controller: _controller,
              decoration: InputDecoration(
                labelText: 'Enter Event Source URL',
              ),
            ),
            SizedBox(height: 16),
            ElevatedButton(
              onPressed: () {
                _startEventListening(_controller.text);
              },
              child: Text('Start Listening'),
            ),
            SizedBox(height: 16),
            Expanded(
              child: ListView.builder(
                itemCount: _events.length,
                itemBuilder: (context, index) {
                  return ListTile(
                    title: Text(_events[index]),
                  );
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

在这个示例中:

  1. 我们创建了一个Flutter应用,包含一个文本输入框用于输入事件源的URL。
  2. 点击“Start Listening”按钮时,应用将尝试连接到指定的URL并监听事件流。
  3. 接收到的事件、连接状态(打开、关闭)和错误将被记录并显示在列表中。

注意:在实际使用中,你需要一个支持SSE的服务器来发送事件。上述代码仅展示了如何在Flutter客户端使用eventsource插件来监听这些事件。

回到顶部