package GitHub repository

Action Channel

Communication channel, that bundles a sink and a stream. Wrapper with convenient functionalities.

Essentially it is a wrapper that acts as a sink and a stream, with additional logic.


  • Allows the input/sink type to be different from the output/stream type, simplifying the entry point.
  • Handling of "replies", allowing it to be used as a request-response channel.
  • Run actions when receiving certain data.

Getting Started

dart pub add action_channel

And import the package:

import 'package:action_channel/action_channel.dart';


Create a channel using a sink and a stream.

You may specify an action to be executed using the data returned in the .on() method.

final channel = Channel(
  sink, stream,
  action: (String data) => print('Action using "$data"')

Listening for data

Listen to the channel with .on(), this will enable you to run an action with the returning data, like a "reply".

final subscription = channel.on((data) {
  print('Data received "$data"');
  return 'New action using "$data"';


You can also use .once() to listen to the channel only once.

Note: The channel can be used just like a stream, with .listen().

Channel Controller

Create a channel using ChannelController, creating a channel that handles the sink and stream, by itself. Abstracting the sink and stream creation.

A controller needs a function that transforms the input/sink data type into the output/stream data type.

It's recommended to use the Channel.controller() factory, which automatically creates a ChannelController.

final channel = Channel<int, String, void>.controller(
  (int id) => User(id),

In addition, it offers callbacks and the ability to append and prepend them.

final channel = Channel<int, String, void>.controller(
  (int id) => User(id),
  onAdded: (int id) => print('User $id added'),
  onData: (User user) => print('User with id "${ }" received'),
  onListen: (subscription) => print('Channel listened'),
  onClose: () => print('Channel closed'),


User Channel (/example/main.dart)
import 'package:action_channel/action_channel.dart'; 

final users = <User>{
  User(1, 'John'),
  User(2, 'Tom', muted: true),
  User(3, 'Alex'),

void main() {
  final channel = Channel<int, User, String>.controller(
    (id) => users.firstWhere((user) => == id),
    action: (message, user, channel) => user.say(message),

  channel.where((user) => !user.muted).on((user) => 'Hello!');

  channel.once((data) {
    print('First user: ${ }');
    return null;


/* -= Models =- */

class User {
  final int id;
  final String name;
  final bool muted;

  User(,, { this.muted = false });

  void say(String message) => print('User $id says "$message"');


Contributions are welcome! Please open an issue or pull request if you find a bug or have a feature request.