flutter_mediator 1.0.0-beta.2 copy "flutter_mediator: ^1.0.0-beta.2" to clipboard
flutter_mediator: ^1.0.0-beta.2 copied to clipboard

outdated

A state management package for flutter.

Flutter Mediator #

Pub

Flutter mediator is a state management package that targets as easy and intuitive to use.

Features #

  • Easy to use - only three steps needed to make things work
  • Lightweight - small package size
  • Efficiency and Performance - use InheritModel as the underlying layer
  • Flexible - provide both automatic and manual observation
  • Intuitive - three main classes: Host, Publisher, Subscriber

Setting up #

Add the following dependency to pubspec.yaml of your flutter project:

dependencies:
  flutter_mediator: "^1.0.0"

Import flutter_mediator in files that will be used:

import 'package:flutter_mediator/mediator.dart';

For help getting started with Flutter, view the online documentation.

Getting Started Quick Steps: #

  1. Extend the model from Publisher
  2. Declare rx variables with .rx which will observe the value automatically.
  3. Implement the update methods.
MyModel.dart
class MyModel extends Publisher {
  // `.rx` make the var automatically rebuild the widget when updated
  var int1 =  0.rx;

  void updateInt1() {
    // int1 is a rx variable, it will automatically rebuild the widget when updated
    int1 +=  1;
  }
  1. Execute the update method, for example, within a RaisedButton.
RaisedButton(
  child: const Text('Update Int1'),
  onPressed: () => context.getModel<MyModel>().updateInt1(),
);
  1. Inject host at the top level of the widget tree.
void  main() {
  runApp(
    MultiHost.create2(
      MyModel(updateMs:  1000), // model that extends Publisher
      ListModel(updateMs:  500),// model that extends Publisher
      child:  MyApp(),
    ),
  /// MultiHost.create1 to MultiHost.create9 are provided by the package.
  /// the original form, for one model:
  // Host(
  //   model: MyModel(updateMs: 1000),
  //   child: MyApp(),
  // ),
  );
}
  1. Subscribe the widget to the host with designated one or more aspect.
    6-1. Choice an aspect to represent the widget.
        In this example, a string type aspect with value of 'int1' is designated.
    6-2. Designate the model to be used.
        In this example, myModel of class MyModel is used.
class Int1Listener extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return 'int1'.subModel<MyModel>(
      create: (context, model) {
        // automatically update when value get updated
        return  Text('Int1 is ${model.int1}');
      },
    );
  }
}
  1. Finally, rx variables used inside the create method will automatically rebuild the widget when its value get updated. (trigger by getter and setter of the value)

Example #

You can find the example in the example folder.

Detail #

  1. single model - host
  2. multiple models - host
  3. automatically update the widget with rx variable - Publisher
  4. access the underlying value directly of rx variable - Publisher
  5. update the value by call style of rx variable - Publisher
  6. manually publish an aspect of the model - Publisher
  7. manually publish more than one aspect of the model - Publisher
  8. manually publish to all aspects of the model - Publisher
  9. future publish of the model - Publisher
  10. rebuild only once per frame for the same aspect - Publisher
  11. writing model helper - Publisher
  12. get model value - Subscriber
  13. subscribe with a single aspect of the model - Subscriber
  14. subscribe with more than one aspect of the model - Subscriber
  15. subscribe with all aspects of the model - Subscriber
  16. subscribe with enum aspects of the model - Subscriber
  17. writing custom rx class

1. single model #

void main() {
  runApp(
    Host(
      model: AppModel(), // model that extends Publisher
      child: MyApp(),
    ),
  );
}

back to detail

2. multiple models #

MultiHost.create1 to MultiHost.create9 are provided by the package.
You can add more MultiHost.createXX method, see multi_host.dart for example.

void main() {
  runApp(
    MultiHost.create2(
      MyModel(updateMs: 1000),  // model that extends Publisher
      ListModel(updateMs: 500), // model that extends Publisher
      child:  MyApp(),
    ),
  );
}

back to detail

3. automatically update the widget #

.rx make the var automatically rebuild the widget when updated

int:
class MyModel extends Publisher {
// `.rx` make the var automatically rebuild the widget when updated
var int1 = 0.rx;

void  updateInt1() {
  int1 += 1; // automatically update aspect related widgets
}
List:
class ListModel extends Publisher {
  // `.rx` make the var automatically rebuild the widget when updated
  final data =  <ListItem>[].rx;

  void updateListItem() {
    // get new item data...
    final newItem = ListItem(itemName, units, color);
    data.add(newItem); // automatically update aspect related widgets
  }

rx variable type of int, double, num, string, bool, list, map, set are provided by the package.
See also RxInt class, RxList class, RxList.add

back to detail

4. access the underlying value directly #

Access the underlying value directly by .value.

MyModel.dart
var int1 = 0.rx;
void updateInt1() {
  // int1 += 1; // automatically update aspect related widget
  /// is the same as
  int1.value += 1; // automatically update aspect related widget
}

back to detail

5. update the value by call style #

MyModel.dart
var _foo = 1.rx;
set foo(int value) {
  _foo(value); // update rx variable by call() style
  /// is the same as
  // _foo = value;
  /// is the same as
  // _foo.value = value;
}

back to detail

6. manually publish an aspect #

MyModel.dart
int manuallyInt = 0;
void manuallyPublishDemo(int value) {
  manuallyInt = value;
  publish('manuallyInt'); // manually publish aspect of 'manuallyInt'
}

back to detail

7. manually publish more than one aspect #

Putting aspects in a list to publish more than one aspect.

MyModel.dart
int _foo = 0;
int _bar = 0;
void increaseBoth() {
  _foo += 1;
  _bar += 1;

  publish(['foo', 'bar']); // manually publish aspects in a list
}

back to detail

8. manually publish to all aspects #

Publish null value to publish to all aspects of the model.

MyModel.dart
void increaseAll() {
  //...
  publish(); // publish to all aspects of the model
}

back to detail

9. future publish #

Use with a future method, for example,

MyModel.dart
int int1 = 0.rx;
Future<void> futureInt1() async {
  await Future.delayed(const Duration(seconds: 1));
  int1 += 1; // int1 is Rx, automatically update aspect related widgets
}

back to detail

10. rebuild only once per frame #

Rebuild only once per UI frame for the same aspect.
Following code only cause the aspect related widgets to rebuild once.

MyModel.dart
int int1 = 0.rx;
void incermentInt1() async {
  int1 += 1;       // int1 is Rx, automatically update aspect related widgets
  publish('int1'); // manually publish 'int1'
  publish('int1'); // manually publish 'int1', again
  // only cause the related widgets to rebuild once per UI frame

}

back to detail

11. writing model helper #

You can write model helpers to simplified the typing. For example,

MyModel.dart
/// Helper function of MyModel
MyModel getMyModel(BuildContext context) {
  return Host.getInheritOfModel<MyModel>(context);
}

Subscriber<MyModel> subMyModel({Key key, Object aspects, @required CreaterOfSubscriber<MyModel> create}) {
  return aspects.subModel<MyModel>(key: key, create: create);
}

extension MyModelHelperT<T> on T {
  Subscriber<MyModel> subMyModel({Key key, @required  CreaterOfSubscriber<MyModel> create}) {
    return Subscriber<MyModel>(key: key, aspects:  this, create: create);
  }
}
ListModel.dart
/// Helper function of ListModel
ListModel getListModel(BuildContext context) {
  return Host.getInheritOfModel<ListModel>(context);
}

Subscriber<ListModel> subListModel({Key key, Object aspects, @required CreaterOfSubscriber<ListModel> create}) {
  return aspects.subModel<ListModel>(key: key, create: create);
}

extension ListModelHelperT<T> on T {
  Subscriber<ListModel> subListModel({Key key, @required CreaterOfSubscriber<ListModel> create}) {
    return Subscriber<ListModel>(key: key, aspects:  this, create: create);
  }
}

back to detail

12. get model value #

To get the model, for example, getting MyModel,

original form
final model = Host.getInheritOfModel<MyModel>(context);
by package helper of context extension
final model = context.getModel<MyModel>();

(See mediator_helper.dart for package helper.)

by model helper on your own
final model = getMyModel(context);

Get current triggered frame aspects of the model.

See also AllListener@main.dart.

final model = context.getModel<MyModel>();
final aspects = model.frameAspect;

back to detail

13. subscribe with a single aspect #

For example, listen to a string type aspect of 'int1'.

original form
class Int1Listener extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Subscriber<MyModel>(
      aspects: 'int1',
      create: (context, model) {
        return Text('Int1 is ${model.int1}');
      },
    );
  }
}
with helper
class Int1Listener extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // return 'int1'.subMyModel(     // with model helper on your own
    return 'int1'.subModel<MyModel>( // with package helper
      create: (context, model) {
        return Text('Int1 is ${model.int1}');
      },
    );
  }
}

back to detail

14. subscribe with more than one aspect #

Putting aspects in a list to subscribe more than one aspect.

original form
class TwoListener extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Subscriber<MyModel>(
      aspects: ['int1', 'star'],
      create: (context, model) {
        return Text('Int1 is ${model.int1} and Star is ${model.star}');
      },
    );
  }
}
with helper
class TwoListener extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // return ['int1', 'star'].subMyModel(     // with model helper on your own
    return ['int1', 'star'].subModel<MyModel>( // with package helper
      create: (context, model) {
        return Text('Int1 is ${model.int1} and Star is ${model.star}');
      },
    );
  }
}

back to detail

15. subscribe with all aspects #

Provide no aspects parameter, or use null as aspect to listen to all aspects.
See also AllListener@main.dart.

original form
class AllListener extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Subscriber<MyModel>(
      // aspects: , // no aspects parameter means listen to all aspects
      create: (context, model) {
        final aspects = model.frameAspect;
        final str = aspects == null ? '' : '$aspects received';
        return Text(str);
      },
    );
  }
}
with helper
class AllListener extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // return null.subMyModel(     // with model helper on your own
    return null.subModel<MyModel>( // with package helper
      create: (context, model) {
        final aspects = model.frameAspect;
        final str = aspects == null ? '' : '$aspects received';
        return Text(str);
      },
    );
  }
}

back to detail

16. subscribe with enum aspects #

You can use enum as aspect type. For example, first, define the enum.

ListModel.dart
enum ListEnum {
  ListUpdate,
}

Then everything is the same as string type aspect just to replace the string with enum.
See also ListItemView@main.dart.

original form
class ListItemView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Subscriber<ListModel>(
      aspects: ListEnum.ListUpdate,
      create: (context, model) {
      //...
    });
  }
}
with helper
class ListItemView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // return  ListEnum.ListUpdate.subListModel(create: (context, model) { // with model helper on your own
    return ListEnum.ListUpdate.subModel<ListModel>(create: (context, model) { // with package helper
      //...
    });
  }
}

back to detail

17. writing custom rx class #

If you need to write your own rx class, see custom_rx_class.dart for example.

back to detail

Changelog #

Please see the Changelog page.

License #

MIT

6
likes
0
pub points
0%
popularity

Publisher

unverified uploader

A state management package for flutter.

Repository (GitHub)
View/report issues

License

unknown (LICENSE)

Dependencies

flutter

More

Packages that depend on flutter_mediator