【Flutter通信】不用插件使用SSE协议
warning:
这篇文章距离上次修改已过205天,其中的内容可能已经有所变动。
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
class ServerSentEventsClient {
static const _defaultHeaders = {
'Accept': 'text/event-stream',
'Cache-Control': 'no-cache',
};
final String url;
final Map<String, String>? headers;
final Duration? timeout;
final void Function(String event, String data)? onEvent;
final void Function(Object error, StackTrace? stackTrace)? onError;
final void Function()? onDone;
late http.Client _httpClient;
late StreamSubscription<String> _subscription;
ServerSentEventsClient(
this.url, {
this.headers,
this.timeout,
this.onEvent,
this.onError,
this.onDone,
}) {
_httpClient = http.Client();
_start();
}
void _start() async {
final response = await _httpClient.get(
Uri.parse(url),
headers: {..._defaultHeaders, ...?headers},
);
if (response.statusCode == 200) {
final stream = response.stream
.transform(utf8.decoder)
.expand((chunk) sync* {
final parts = chunk.toString().split('\n');
for (var part in parts) {
if (part.isNotEmpty) {
yield part;
}
}
})
.where((line) => line.isNotEmpty)
.map((line) {
final parts = line.split(':');
return MapEntry(
parts[0].trim(),
parts.length > 1 ? parts.sublist(1).join(':').trim() : null,
);
});
_subscription = stream.listen((event) {
final data = <String, String?>{};
if (event['data'] != null) {
final map = jsonDecode(event['data']);
map.forEach((key, value) {
data[key] = value?.toString();
});
}
onEvent?.call(event['event'] ?? '', jsonEncode(data));
}, onError: (error, stackTrace) {
onError?.call(error, stackTrace);
}, onDone: () {
onDone?.call();
});
} else {
// Handle error response
}
}
void dispose() {
_subscription.cancel();
_httpClient.close();
}
}
// 使用方法
void main() {
final client = ServerSentEventsClient(
'https://example.com/stream',
onEvent: (event, data) {
print('Event: $event, Data: $data');
},
onError: (error, stackTrace) {
print('Error: $error');
},
onDone: () {
print('Stream is done.');
评论已关闭