inherited_model_macro 0.1.2 copy "inherited_model_macro: ^0.1.2" to clipboard
inherited_model_macro: ^0.1.2 copied to clipboard

Macro that generates boilerplate code for InheritedModel and simplifies state management

Macro that generates boilerplate code for InheritedModel and simplifies state management #

Dart macros feature was under development and is currently suspended, so this package may not work and won't be fixed until macros feature is released.

Declare class with field (and methods to update them) and annotate it with @InheritedModelMacro() to generate code for full InheritedModel (it must extend InheritedModel<String>):

 @InheritedModelMacro()
 class LogoModel extends InheritedModel<String> {
   final Color? backgroundColor; // setting values to null is also supported in update methods
   final bool large;

   void toggleColor(BuildContext context) {
     final newValue = (backgroundColor == null) ? Colors.red : null;
     updateState(backgroundColor: newValue); // updateState is generated method
   }

   void toggleSize(BuildContext context) {
     updateState(large: large != true);
   }
 }

Then insert generated Holder class in a tree like Provider or InheritedWidget and provide initial values for fields:

Scaffold(
   body: const LogoModelHolder(
     backgroundColor: Colors.blue,
     large: false,
     child: Content(),
 )

In your class this code will be generated:

class LogoModel {
  // get field value
  static FieldType readField(context) // for every field

  // get field value and subscribe to it's changes. When value changes, widget will be redrawn
  static FieldType watchField(context) // for every field

  // find instance and update given fields
  static void update(context, {fields?}) 

  // update fields directly
  void updateState({fields?}) 

  // get nearest instanse of class up in the tree
  static Type getInstance(context) 
}

Then you can use it like this:

// get current value and update it
final currentSize = LogoModel.readLarge(context);
LogoModel.update(context, large: !currentSize);

// subscribe to changes 
final Color? color = LogoModel.watchBackgroundColor(context);

Usage can also be found in example. Generated code is presented here.

Notes: #

  • Your class MUST extends InheritedModel<String> until future versions when macros feature extendType stops breaking analyzer
  • Dart sdk version must be ^3.5.0-152 or higher and macros must be enabled in analysis_options.yaml and during build (Documentation)
  • Analyzer might throw errors that generated code is not there when applying macro on different projects other than macro itself (issue). Instead of working with code, that does not exist, you can try to dart unpack this package into your project

Under the hood #

Holder class provided setState callback to your class that updates values inside holder and provides them down to your class.

InheritedModel, like other InheritedWidgets, is needed for O(1) tree search. But it's marked @immutable, so all fields are supposed to be final and can't be changed -> are provided by holder.

Also InheritedModel is useful as it allows to separatly subscribe to changes of fields. This is done by passing field name as aspect to inheritFrom method. That is why your class must extend InheritedModel<String>.

Setting nullable fields are implemented by getting Object stub in case of passing nothing as default argument and comparing it to current field value.

The rest is basic InheritedModel boilerplate code.

0
likes
50
points
34
downloads

Publisher

unverified uploader

Weekly Downloads

Macro that generates boilerplate code for InheritedModel and simplifies state management

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, macros, meta

More

Packages that depend on inherited_model_macro