Introduction
The piesocket_channels Flutter package (pub.dev name piesocket_channels) gives you low‑latency, bidirectional WebSocket communication across all Flutter platforms. It abstracts connection handling, channel subscription, and message encoding, letting you focus on UI and business logic.
When to Use piesocket_channels
- Live chat or messaging systems
- Collaborative document or whiteboard editing
- Multiplayer game state synchronization
- IoT sensor streams, stock tickers, sports scores
If your app needs real‑time updates and you prefer a pure‑Dart solution without managing a separate server stack, piesocket_channels is a solid choice.
Installation
Add the package to your pubspec.yaml using the Flutter CLI:
flutter pub add piesocket_channelsAfter the command completes, run flutter pub get to fetch the dependency.
Basic Setup
First, obtain an API key from Pie.host. The key is required to authenticate your client.
Tip: Keep your API key out of version control. Store it in a secure place such as.envor use Flutter's--dart-defineflags.
Below is a minimal example that connects to a channel called demo-room, listens for incoming messages, and publishes user input.
import 'package:flutter/material.dart';
import 'package:piesocket_channels/piesocket_channels.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: ChatPage(),
);
}
}
class ChatPage extends StatefulWidget {
const ChatPage({Key? key}) : super(key: key);
@override
_ChatPageState createState() => _ChatPageState();
}
class _ChatPageState extends State {
// Replace with your actual Pie.host API key.
final _client = PieSocketClient(apiKey: 'YOUR_API_KEY');
late final PieSocketChannel _channel;
final _controller = TextEditingController();
final List _messages = [];
@override
void initState() {
super.initState();
// Create and subscribe to a channel.
_channel = _client.channel('demo-room');
_channel.subscribe();
// Listen to the channel's stream.
_channel.stream.listen((msg) {
setState(() {
_messages.add(msg.data as String);
});
});
}
void _send() {
final text = _controller.text.trim();
if (text.isNotEmpty) {
_channel.publish(text);
_controller.clear();
}
}
@override
void dispose() {
_channel.dispose();
_client.dispose();
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('PieSocket Chat')),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: _messages.length,
itemBuilder: (context, index) => ListTile(
title: Text(_messages[index]),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: TextField(
controller: _controller,
decoration: const InputDecoration(
hintText: 'Type a message',
),
onSubmitted: (_) => _send(),
),
),
IconButton(
icon: const Icon(Icons.send),
onPressed: _send,
),
],
),
),
],
),
);
}
}This example demonstrates the core workflow:
- Create a
PieSocketClientwith your API key. - Obtain a
PieSocketChannelviaclient.channel('room-name'). - Call
subscribe()to start receiving messages. - Listen to
channel.streamfor incoming data. - Publish messages with
channel.publish(payload). - Dispose of the channel and client when the widget is removed.
Integrating with StreamBuilder
If you prefer a declarative UI, you can expose the channel stream directly to a StreamBuilder:
StreamBuilder<PieSocketMessage>(
stream: _channel.stream,
builder: (context, snapshot) {
if (snapshot.hasData) {
final msg = snapshot.data!.data as String;
return Text('New: $msg');
}
return const Text('No messages yet');
},
);Advanced Configuration
- Reconnection logic: The SDK includes built‑in reconnection, but you can customize the back‑off strategy via the client’s constructor (check the docs for the exact parameters).
- Message encoding: By default,
publish()sends a string. For JSON payloads, encode withjsonEncode()and decode in the listener. - Presence & authentication: Some Pie.host plans support presence events. If you need per‑user authentication, pass a JWT token in the client options.
Mistakes to Avoid
Common pitfalls include forgetting to call dispose() on the channel/client, which can leave stray WebSocket connections open, and publishing non‑serializable objects (the server expects a string or JSON‑serializable payload).
- Never hard‑code the API key in production builds.
- Always handle
onErroron the stream to avoid uncaught exceptions. - Respect the free‑tier connection limits; monitor usage in the Pie.host dashboard.
Testing Locally
The package works on all Flutter targets (Android, iOS, Web, macOS, Linux, Windows). When testing on the web, ensure your browser allows WebSocket connections to wss://*.pie.host. For mobile emulators, verify network connectivity.
Conclusion
The piesocket_channels Flutter package offers a clean, Dart‑first API for real‑time communication. By following the steps above, you can add live chat, game state sync, or any pub/sub feature to your Flutter app with minimal boilerplate.
Frequently Asked Questions
Do I need a server when using piesocket_channels?
No. The package connects directly to Pie.host's WebSocket infrastructure, so you only need a Pie.host API key. However, you may still run a backend for authentication or business logic if required.
Can I use piesocket_channels on the web?
Yes. The SDK is pure Dart and works on Flutter Web. Just ensure the browser permits WebSocket connections to the Pie.host domain and that you serve your app over HTTPS.
How do I handle JSON messages?
Encode your payload with <code>jsonEncode()</code> before publishing, and decode inside the listener with <code>jsonDecode()</code>. Example:
<pre><code class="language-dart">_channel.publish(jsonEncode({'type':'chat','text':msg}));
_channel.stream.listen((msg) {
final data = jsonDecode(msg.data as String);
// use data['text']
});
</code></pre>What should I do if the connection drops frequently?
The package includes automatic reconnection, but you can monitor the <code>client.connectionState</code> stream to show UI feedback. Also verify that your API key has sufficient quota and that network firewalls aren’t blocking WebSocket traffic.