Signal

"signal" - Multiple state management in one channel

Stream-based multiple state management. Multiple state management in one channel. Similar to the bloc structure, but current states are always accessible.

Usage

Create channel and its signal.


abstract class MyChannelSignal extends ChannelSignal {}

class MyChannel extends StateChannel<MyChannelSignal> {
  MyChannel() {
    _counterState = CounterState(() => add(CounterStateSignal()));
    _notificationState = NotificationState(() => add(NotificationStateSignal()));
  }

//signal: CounterStateSignal
  late CounterState _counterState;
  CounterState get counterState => _counterState;

//signal: NotificationStateSignal
  late NotificationState _notificationState;
  NotificationState get notificationState => _notificationState;

  @override
  void initState() {
    _counterState.initState();
    _notificationState.initState();
  }

  @override
  afterInitState() {
    _counterState.afterInitState();
    _notificationState.afterInitState();
  }

  @override
  void dispose() {
    _counterState.dispose();
    _notificationState.dispose();
    super.dispose();
  }
}

Create states and its signals


class CounterStateSignal extends MyChannelSignal {}

class CounterState extends BaseState {
  CounterState(void Function() onStateChanged) : super(onStateChanged);

  int _count = 0;
  int get count => _count;

  @override
  void initState() {
    wait(signal: false);
    _count = 0;
  }

  @override
  Future<void> afterInitState() async {
    await incrementFuture();
  }

  @override
  void dispose() {}

  void increment() {
    _count = _count + 1;
    doneSuccess();
  }

  void decrement() {
    _count = _count - 1;
    doneSuccess();
  }

  Future<void> incrementFuture() async {
    try {
      wait();
      await Future<void>.delayed(Duration(seconds: 5));
      _count = _count + 1;

      doneSuccess();
    } catch (e) {
      doneError(e.toString());
    }
  }

  Future<void> decrementFuture() async {
    try {
      wait();
      await Future<void>.delayed(Duration(seconds: 1));
      _count = _count - 1;

      doneSuccess();
    } catch (e) {
      doneError(e.toString());
    }
  }
}

class NotificationStateSignal extends MyChannelSignal {}

class NotificationState extends BaseState {
  NotificationState(void Function() onStateChanged) : super(onStateChanged);

  bool _isOpen = false;
  bool get isOpen => _isOpen;

  @override
  initState() {
    wait(signal: false);
    _isOpen = false;
  }

  @override
  Future<void> afterInitState() async => await changeFuture();

  @override
  dispose() {}

  change() {
    _isOpen = !_isOpen;
    doneSuccess();
  }

  Future<void> changeFuture() async {
    try {
      wait();
      await Future<void>.delayed(Duration(seconds: 1));
      _isOpen = !_isOpen;

      doneSuccess();
    } catch (e) {
      doneError(e.toString());
    }
  }
}

ChannelProvider

Creates a channel, store it, and expose it to its descendants. A ChannelProvider manages the lifecycle of the channel.

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChannelProvider<MyChannel>(
        channel: (context) => MyChannel(),
        child: MaterialApp(
          debugShowCheckedModeBanner: false,
          home: HomePage(),
        ));
  }
}


ChannelBuilder

ChannelBuilder handles building a widget in response to new ChannelSignal broadcasting from ChannelProvider on an.

 
ChannelBuilder<MyChannel, MyChannelSignal>(
    condition: (channel, signal) => signal is CounterStateSignal,
    builder: (context, channel, _) => 
      channel.counterState.busy ? CircularProgressIndicator():
      !channel.counterState.success ? Text(channel.notificationState.error) :
      Text(channel.counterState.count.toString()),
  ),

that's all.

Signal Example

Libraries

signal