Reputation: 1679
In developing some of the screens for my flutter app, I regularly need to dynamically render widgets based on the state of the screen. For circumstances where it makes sense to create a separate widget and include it, I do that.
However, there are many use cases where what I need to render is not fit for a widget, and leverages existing state from the page. Therefore I use builder methods to render the appropriate widgets to the page. As anyone who uses Flutter knows, that can lead to lengthy code where you need to scroll up/down a lot to get to what you need to work on.
For better maintainability, I would love to move those builder methods into separate files, and then just include them. This would make it much easier to work on specific code widgets rendered and make the screen widget much cleaner.
But I haven't found a proper way to extract that dynamic widget code, which makes use of state, calls to update state, etc. I'm looking for a type of "include" file that would insert code into the main screen and render as if it's part of the core code.
Is this possible? How to achieve?
Upvotes: 2
Views: 828
Reputation: 126664
With the introduction of extension
members, I came across this really neat way of achieving exactly what your described!
Say you have a State
class defined like this:
class MyWidgetState extends State<MyWidget> {
int cakes;
@override
void initState() {
super.initState();
cakes = 0;
}
@override
Widget build(BuildContext context) {
return Builder(
builder: (context) => Text('$cakes'),
);
}
}
As you can see, there is a local variable cakes
and a builder
function. The very neat way to extract this builder now is the following:
extension CakesBuilderExtension on MyWidgetState {
Widget cakesBuilder(BuildContext context) {
return Text('$cakes');
}
}
Now, the cakes
member can be accessed from the extension
even if the extension is placed in another file.
Now, you would update your State
class like this (the builder
changed):
class MyWidgetState extends State<MyWidget> {
int cakes;
@override
void initState() {
super.initState();
cakes = 0;
}
@override
Widget build(BuildContext context) {
return Builder(
builder: cakesBuilder,
);
}
}
The cakesBuilder
can be referenced from MyWidgetState
, even though it is only declared in the CakesBuilderExtension
!
The extension
feature requires Dart 2.6. This is not yet available in the stable channel, but should be around the end of 2019 I guess. Thus, you need to use the dev
or master
channels: flutter channel dev
or flutter channel master
and update the environment
constraint in your pubspec.yaml
file:
environment:
sdk: '>=2.6.0-dev.8.2 <3.0.0'
Upvotes: 3