On the previous post, I was simply creating a new Flutter web application project using their default template. It's a simple way to learn the basic commands and already have an idea where all the artifacts are stored. Not really interesting though, no code, no modification, just few shell commands executed.
Dart/Flutter main entry point can be found in lib/main.dart, at this time, it only contains code from the template (comments were removed). Let explain each blocks.
import 'package:flutter/material.dart';
Flutter is using Dart, and Dart has a modular approach like many modern languages. Public packages can be found on pub.dev. Here, the application is looking for the flutter/material library. Material is a design system/library and will be used for all the front-end UI/UX thingies.
void main() {
runApp(const MyApp());
}
In Dart, the function entry-point is called main() and - currently - can't be changed but using another file as entry-point can be done using flutter run -t lib/other_file.dart. Anyway, this snippet call the runApp() function coming directly from Flutter. Its argument is a Widget object containing elements of the page. In our case MyApp() is an object created using MyApp class defined below.
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: .fromSeed(seedColor: Colors.deepPurple),
),
home: const MyHomePage(
title: 'Flutter Demo Home Page'
),
);
}
}
MyApp class extends the Flutter StatelessWidget class. First, let try to understand what extends mean in this context. From the dart documentation, extends creates a subclass, it will then inherit methods and attributes from the main class and give the ability to add new methods and/or attributes to it. Here, MyApp will extend the StatelessWidget class.
A stateless widget is a widget that describes part of the user interface by building a constellation of other widgets that describe the user interface more concretely [...] For compositions that can change dynamically, e.g. due to having an internal clock-driven state, or depending on some system state, consider using
StatefulWidget.
-- Flutter StatelessWidget class
The next part of the class definition overrides the build() method, used to describe the user interface represented by the widget. The @override annotation is used to override the instance method. This method must return a Widget object, in this case, the template is using the MaterialApp class as object constructor, mostly used to configure and wrap many required values from Material Design applications.
A convenience widget that wraps a number of widgets that are commonly required for Material Design applications [...] The MaterialApp configures the top-level Navigator to search for routes.
-- Flutter MaterialApp class
Three attributes/arguments are passed to the constructor:
titleattribute set the title of the page;themeattribute set the theme of the page (color, fonts and shapes);homeattribute configure the default route of the application. This parameter is configured in the next paragraph.
class MyHomePage extends StatefulWidget {
const MyHomePage({
super.key,
required this.title
});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
MyHomePage class is extending StatefulWidget class. Like for the StatelessWidget class, this is a container, but this time, with mutable properties. Here the syntax can be a bit confusing, the const MyHomePage() part is a constant constructor where super.key is the key property from the Widget class and this.title is the title property defined in MyApp class.
Finally, this snippet override createState() method, and returns a custom object from _MyHomePageState() defined below. Few notes from the documentation:
Creates the mutable state for this widget at a given location in the tree. Subclasses should override this method to return a newly created instance of their associated State subclass.
-- Flutter StatefulWidget createState method
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: .center,
children: [
const Text('You have pushed the button this many times:'),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
The last class implemented there is _MyHomePageState extending the class State. Managing states in Dart/Flutter seems to be quite... complex. Firstly, it could be great to explain the syntax of State<MyHomePage> in the class definition. This part means the subtype must be using MyHomePage type, this is called parameterized type.
Two local definitions are then created, the _counter attribute, used to store the number of time someone clicked on a button and _incrementCounter() method, incrementing _counter attribute. _ (underscore) here is not only a convention, but makes those private (based on stack overflow answer) and from the documentation:
Unlike Java, Dart doesn't have the keywords
public,protected, andprivate. If an identifier starts with an underscore (_), it's private to its library. For details, see Libraries and imports. Identifiers can start with a letter or underscore (_), followed by any combination of those characters plus digits.
-- Dart Important Concepts
Finally, the last part of code to explain is the redefinition of build() method from the StatefulWidget class. This time, this method return a Scaffold object, from the documentation:
Implements the basic Material Design visual layout structure. This class provides APIs for showing drawers and bottom sheets.
-- Flutter Documentation Scaffold class
It seems pretty clear this is the place where all the magic happens. The Scaffold object generated will be in charge to create an AppBar, deal with the page body using a Center object and add a button using a FloatingActionButton object. The final result when this code is executed can be seen in the screenshot below.
Now, few remarks regarding Dart and Flutter syntax. Variables, attributes, methods and/or functions can be used in string using $ (dollar) symbol, like mentioned in the core documentation:
You can use ${} to interpolate the value of Dart expressions within strings. The curly braces can be omitted when evaluating identifiers:
-- String class
It looks like a constant can be used simply by using its name without its class origin like in .center. It should be equivalent to MainAxisAlignment.center. I always found this kind of syntax highly confusing, with the same level of confusion than this and super.
The end of the file has been reached. Dart and Flutter are interesting, but the object paradigm is still a big mess with lot of implicit reference, mostly due to the syntax. Anyway, when one is coming from functional programming and in particular Erlang/Elixir/Prolog, it's hard to deal with this kind of philosophy.
Cover Image by Anastase Maragos on Unsplash

Top comments (0)