functional_widget 0.4.0
functional_widget: ^0.4.0 copied to clipboard
A code generator that generates widget classes from their implementation as a function.
Widgets are cool. But classes are quite verbose:
class Foo extends StatelessWidget {
final int value;
final int value2;
const Foo({Key key, this.value, this.value2}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text('$value $value2');
}
}
Worse than that, we also likely want to override operator==
and debugFillProperties
too!
So much code for something that could be done much better using a plain function:
Widget foo(BuildContext context, { int value, int value2 }) {
return Text('$value $value2');
}
The problem is, using functions instead of classes is not recommended:
- https://stackoverflow.com/questions/53234825/what-is-the-difference-between-functions-and-classes-to-create-widgets/53234826#53234826
- https://github.com/flutter/flutter/issues/19269
... Or is it?
Here comes functional_widgets, a code generator that generates widget classes from functions.
Simply write your widget as a function, decorate it with a @widget
, and then this library will generate a class for you to use.
Example #
- You write:
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
@widget
Widget foo(BuildContext context, int value) {
return Text('$value');
}
Make sure to include import 'package:flutter/foundation.dart';
. This is a requirement for debugFillProperties
to work.
- It generates:
class Foo extends StatelessWidget {
const Foo(this.value, {Key key}) : super(key: key);
final int value;
@override
Widget build(BuildContext _context) => foo(value);
@override
int get hashCode => value.hashCode;
@override
bool operator ==(Object o) =>
identical(o, this) || (o is Foo && value == o.value);
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(IntProperty('value', value));
}
}
- You use it:
runApp(
Foo(42)
);
Notice that we use Foo
and not foo
. Foo
is the generated class while foo
is the function you wrote.
How to use #
Install #
There are a few separate packages you need to install:
functional_widget_annotation
, a package containing decorators. You must install it asdependencies
.functional_widget
, a generator that uses the decorators from the previous packages to generate your widget. Install it asdev_dependencies
build_runner
, a tool that is able to run code-generators. Install it asdev_dependencies
dependencies:
functional_widget_annotation: ^0.3.0
dev_dependencies:
functional_widget: ^0.4.0
build_runner: ^1.1.2
Run the generator #
To run the generator, you must use build_runner
cli:
flutter pub pub run build_runner watch
All the potential syntaxtes #
functional_widget will inject widget specific parameters if you ask for them. You can potentially write any of the following:
Widget foo();
Widget foo(BuildContext context);
Widget foo(Key key);
Widget foo(BuildContext context, Key key);
Widget foo(Key key, BuildContext context);
You can also replace BuildContext
by HookContext
from https://github.com/rrousselGit/flutter_hooks
You can then add however many arguments you like after the previously defined arguments. They will then be added to the class constructor and as a widget field:
- positional
@widget
Widget foo(int value) => Text(value.toString());
// USAGE
new Foo(42);
- named:
@widget
Widget foo({int value}) => Text(value.toString());
// USAGE
new Foo(value: 42);
- A bit of everything:
@widget
Widget foo(BuildContext context, int value, { int value2 }) {
return Text('$value $value2')
}
// USAGE
new Foo(42, value2: 24);