Intro to Flutter Composition and Stateless Widgets

  1. Widgets in Flutter
  2. Code along
    1. Structural widgets
    2. Stylistic widgets
    3. Layout widgets
  3. Composition and the widget tree
    1. Planning a UI in Flutter
  4. Stateless widgets
    1. The build() method
  5. Other tips and tricks
  6. Key terms

Widgets in Flutter

A widget is “an immutable description of a part of a user interface” according to the (Flutter documentation). Widgets are the individual parts of the UI that provide structure, style, and layout on the screen. UIs in Flutter are composed of many widgets.

In Flutter, widgets are divided into two types: stateless and stateful. We will talk about the distinction later. In terms of what the widgets do, you can group Flutter widgets into through categories:

Flutter has dozens of built-in widgets for you to use and customize. We will start with some basic widgets so that you can become familiar with composition.

Code along

We are going to code a new Flutter project together in class to explain the basics of Flutter composition and use a few widgets.

Structural widgets

Stylistic widgets

Layout widgets

Composition and the widget tree

Hopefully you are now starting to see how Flutter widgets are composed together. Composition is the combining of widgets together to create a UI. Each widget has one simple job. Composition in Flutter means that one widget will often “contain” another. Programmatically, this means that one object has a reference (a variable) holding another object. In the built-in Flutter widget classes, the child variable usually holds the reference.

Widgets are composed into a widget tree. The widget tree usually has a StatelessWidget as its root, CollageApp in our example. The CollageApp defines the build() method, which then returns a MaterialApp. The MaterialApp contains a Scaffold, which contains an AppBar and a Center, which contains… And on and on.

Drawing the widget tree is a great way to help you understand how Flutter thinks of your app. The starting point, from a programming perspective, of a Flutter app is the runApp() function call that takes a widget as a parameter. This widget is the root of the widget tree. Flutter then traverses the tree (remember data structures?) to figure out where to position widgets on the screen while taking into account the desired size of each widget against the amount of actual pixels available.

Think of the widget tree you compose with your Dart code as a blueprint for Flutter. Flutter uses your widget tree to figure out very specifically how to instruct your phone to draw things on the screen. There is a separate, parallel structure called the element tree that is in memory while your app is running that represents the actual widgets displayed on the screen at the given time.

Planning a UI in Flutter

When designing a UI, sketch out on paper a very simple drawing of what goes where on the screen. then, think about what widgets you will need to realize this and sketch out the widget tree. Your widget tree need not be perfect, but it will help you figure out how to compose the code. It is easy in Flutter to get confused with all the code nesting. Better to have a visual blueprint to refer to.

Stateless widgets

Flutter widgets are one of two types: stateless or stateful. All widget classes in Flutter inherit from either the StatelessWidget or StatefulWidget classes.

A stateless widget is one that does not change after it is first drawn on the screen. It is effectively immutable once rendered. Text, Padding, and BoxDecoration are all examples of stateless widgets. You can configure their style and content in the code, but once they are showing on the screen, they are not able to be changed. Contrast this to a Checkbox or Search Box whose appearance will change when a user interacts with it. Checkboxes and Search Boxes are stateful.

Stateless widgets can have children, i.e., can refer to other widgets for composition. Flutter has many built-in stateless widgets, but you can also define your own widget (which will be composed of built-in widgets) by extending the StatelessWidget class. This is great for when you have a particular style you want to create for a widget and use that same style in multiple places.

Just like Flutter’s built-in widgets, you can define a constructor on your StatelessWidget that will accept parameters to specify how your widget should behave. For example, you can define a StatelessWidget that displays text in a colorful “card”, and your constructor can take a parameter that specifies which string you want to show.

The build() method

Every subclass of StatelessWidget must override the build() method. The build() method is automatically called by Flutter when it is time to draw your widget on the screen. Remember, widgets are best thought of as blueprints or configurations for the app’s UI. Flutter will process your widgets and transform them into elements. An element is a widget that has been made real and mounted on the screen. Each Widget class has a corresponding Element class, e.g., StatelessWidget has a StatelessElement class.

So, when exactly is the build() method called? What starts the process of building and creating the elements?

  1. runApp is the starting point. Whatever Widget is given to it, Flutter tries to create that Element to the height and width constraints that match the screen. runApp() is called when the user launches your app on their device.
  2. Flutter asks the Widget for an Element, and then puts that element on the element tree with a reference to the widget that created it. The element tree always represents what is actually displayed on the device at any given moment.
  3. Flutter then calls the widget’s build method to get any child elements. They are mounted on the element tree as well.

Other tips and tricks

Key terms

UI
user interface
page or screen
We use these terms to refer to a collection of widgets that appear together and fill the screen. Different pages often have different logical purposes, like a “View Profile” page, “Upload Pictures” page, “Search for Items to Buy” page, etc. We will cover creating multiple pages and navigating between them soon.
Widget
a widget is an individual part of the UI that provides structure, style, and layout on the screen. Widgets are blueprints for what Flutter should draw on the screen.
Element
a widget made real on the screen. Flutter creates elements on the screen by examining your widgets, and does the hard work of telling the phone how to draw the elements on the screen while considering different screen sizes and other constraints.
Composition
Combining widgets together to create a UI. Each widget has one simple job. Composition in Flutter means that one widget will often “contain” another. Programmatically, this means that one object has a reference (a variable) holding another object. In the built-in Flutter widget classes, the child variable usually holds the reference.
Widget tree
The composition of widgets that create the UI. You specify your widget tree by composing Flutter widgets in your code, and when the app runs, Flutter traverses your logical widget tree to figure out what and how to render the widgets into UI elements on the physical screen.
Element tree
A tree that represents what is actually displayed on the device at any given moment. It has a parallel structure to the widget tree.
Material design
You may see or hear the term “material” when watching videos or reading Flutter documentation. Material Design is Google’s design language that they use in all their services and apps. It is characterized by the metaphor that UI elements are “cards” or “materials” sitting on top of a surface.