Flutter Builders
The term closure is just another name for a lambda function, an anonymous method.
So, builder is really a lambda that acts similarly to the Widget’s build method:
You pass it a BuildContext and any other variables you need to.
It returns a Widget.
How Do You Use a Builder?
Instead of passing a Widget back from your build method, instead you pass back an anonymous builder function that takes whatever
parameters are required (including the BuildContext) and spits out a Widget.
Nested Builders
You can nest builders inside builders and this (although sometimes complicated) works very well. There is an example in this Chapter
called ‘Multiple Builders’, which uses nested builders.
Common Builders
AnimatedBuilder
We will cover this builder in the Animations chapter.
GridView Builder
Similar to the ListView builder. Quite often you will end up with large dynamic data grids and you need to display them onscreen using a
Grid, even though the user may not scroll all the way to the bottom.
If you simply add a Widget for each item in the grid, you end up with a huge amount of child Widgets, most of which will never be seen. This is not efficient.
This is where the GridView builder comes in. When the user scrolls down through the grid, the GridView builder is invoked to create the
child widgets when they are needed, not ahead of time. Much more efficient.
You write a GridView builder and specify it to the GridView in the ‘itemBuilder’ argument in the constructor. In the builder method, you
accept BuildContext and index arguments and you spit out a Widget.
This is perfect if your data is held in array – all you do is get the data for that item from the array using that index.
There is an example in this Chapter called ‘Multiple Builders’. It uses the GridView builder, amongst other builders!
FutureBuilder
FutureBuilder is a widget that returns another widget based on the Future’s execution result. It serves as a bridge between Futures and the widget’s UI.
Example – ‘future_builder_app’
This app uses a FutureBuilder to calculates a bunch of timestamps using a Future computation and display it. The screen is blank for a
few seconds then it displays a list of times. It’s not terribly pretty!
Source Code:
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Future Builder App',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new HomeWidget(),
);
}
}
class HomeWidget extends StatefulWidget {
String computeListOfTimestamps(int count) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < count; i++) {
sb.writeln("${i + 1} : ${DateTime.now()}");
}
return sb.toString();
}
Future<String> createFutureCalculation(int count) {
return new Future(() {
return computeListOfTimestamps(count);
});
}
HomeWidget({Key key}) : super(key: key);
@override
_HomeWidgetState createState() => new _HomeWidgetState();
}
class _HomeWidgetState extends State<HomeWidget> {
bool _showCalculation = false;
void _onInvokeFuturePressed() {
setState(() {
_showCalculation = !_showCalculation;
});
}
@override
Widget build(BuildContext context) {
Widget child = _showCalculation
? FutureBuilder(
future: widget.createFutureCalculation(10000),
builder: (BuildContext context, AsyncSnapshot snapshot) {
return Expanded(
child: SingleChildScrollView(
child: Text(
'${snapshot.data == null ? "" : snapshot.data}',
style: TextStyle(fontSize: 20.0))));
})
: Text('hit the button to show calculation');
return new Scaffold(
appBar: new AppBar(
title: new Text("Future"),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[child])),
floatingActionButton: new FloatingActionButton(
onPressed: _onInvokeFuturePressed,
tooltip: 'Invoke Future',
child: new Icon(Icons.refresh),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}