Published was inspired by Published property wrapper from Swift.

There are approaches like using BloC that depend on streams and they introduce a lot of boilerplate.

Published goal is reduce that boilerplate and introduce simple state management.

How to use


To use package:published in your package, add these dependencies to your pubspec.yaml.




import 'package:published/published.dart';

part 'counter_view_model.published.dart';

abstract class CounterViewModel extends _$CounterViewModel {
  abstract int count;

  void increment() => count++;

  bool get enableLogging => true;

You'll have to make abstract class and annotate it with @published and extend it with _$ClassName.

Annotate abstract field for which you want to expose stream with @Publisher().

  • Note: It's important to use abstract fields and classes so we can replicate Swift structs.

Then run pub run build_runner build to generate files into your source directory.

> pub run build_runner build
[INFO] ensureBuildScript: Generating build script completed, took 368ms
[INFO] BuildDefinition: Reading cached asset graph completed, took 54ms
[INFO] BuildDefinition: Checking for updates since last build completed, took 663ms
[INFO] Build: Running build completed, took 10ms
[INFO] Build: Caching finalized dependency graph completed, took 44ms
[INFO] Build: Succeeded after 4687ms with 1 outputs

NOTE: If you're using Flutter, replace pub run with flutter packages pub run.

To use it do following

 final model = 0);

 Widget build(BuildContext context) {
   return Scaffold(
      body: Center(
        child: Column(
          children: <Widget>[
              'You have pushed the button this many times:',
              stream: model.$count,
              builder: (context,snapshot) => Text("${ ?? 0}");
      floatingActionButton: FloatingActionButton(
        onPressed: () => model.count++,
        tooltip: 'Increment',
        child: Icon(Icons.add),

$ needs to be used to create instance of the object. If you don't want to pass default value in build() use defaultValue property on Publisher like this:

@Publisher(defaultValue: "John")
abstract String name;

To observe if any property annotated with Publisher changed you can use didChange:

model.didChange.listen(() => doSomething())

If you want to enableLogging you can override getter enableLogging:

abstract class CounterViewModel extends _$CounterViewModel {
  bool get enableLogging => true;

Finally if you want to do something on object creation you can override onBind method and place your logic there:

abstract class CounterViewModel extends _$CounterViewModel {
  void onBind() {