Chapters

Hide chapters

Flutter Apprentice

First Edition – Early Access 3 · Flutter 1.22.6 · Dart 2.10.5 · Android Studio 4.1.2

Section III: Navigating Between Screens

Section 3: 3 chapters
Show chapters Hide chapters

Section IV: Networking, Persistence and State

Section 4: 7 chapters
Show chapters Hide chapters

Appendices

Section 6: 2 chapters
Show chapters Hide chapters

4. Understanding Widgets
Written by Vincent Ngo

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

You may have heard that everything in Flutter is a widget. While that might not be absolutely true, most of the time when you’re building apps, you only see the top layer: widgets. In this chapter, you’ll dive into widget theory. You’ll explore:

  • Widgets
  • Widget rendering
  • Flutter Inspector
  • Types of widgets
  • Widget lifecycle

It’s time to jump in!

Note: This chapter is mostly theoretical. You’ll make just a few code changes to the project near the end of the chapter.

What is a widget?

A widget is a building block for your user interface. Using widgets is like combining Legos. Like Legos, you can mix and match widgets to create something amazing.

Flutter’s declarative nature makes it super easy to build a UI with widgets. A widget is a blueprint for displaying your app state.

You can think of widgets as a function of UI. Given a state, the build() method of a widget constructs the widget UI.

Unboxing Card2

In the previous chapter, you created three recipe cards. Now, you’ll look in more detail at the widgets that compose Card2:

Widget trees

Every widget contains a build() method. In this method, you create a UI composition by nesting widgets within other widgets. This forms a tree-like data structure. Each widget can contain other widgets, commonly called children. Below is a visualization of Card2’s widget tree:

Rendering widgets

In Chapter 1, “Introduction”, you learned that Flutter’s architecture contains three layers:

Three trees

Flutter’s framework actually manages not one, but three trees in parallel:

Types of elements

There are two types of elements:

Example trees for Card2

The image below shows an example of the three trees for the Card2 UI:

Getting started

Open the starter project in Android Studio, run flutter pub get if necessary, then run the app. You’ll see the Fooderlich app from the previous chapter:

DevTools overview

DevTools provides all kinds of awesome tools to help you debug your Flutter app. These include:

Flutter Inspector

The Flutter Inspector has four key benefits. It helps you:

Flutter Inspector tools

Here are some of the important tools to use with the Flutter Inspector.

Inspecting the widget tree

In the emulator, select the first tab, then click Refresh Tree in the DevTools. Finally, select Card1, as shown below:

Layout Explorer

Next, click the Layout Explorer tab, as shown below:

Types of widgets

There are two major types of widgets: stateless and stateful widgets. You’ll take a closer look at the differences between them next.

Stateless widgets

Stateless Widgets are immutable. You can’t alter the state or properties of this widget once built. When your properties don’t need to change over time, it’s generally a good idea to start with a stateless widget.

Stateful widgets

Stateful widgets preserve state, which is useful when parts of your UI need to change dynamically.

State object lifecycle

Every widget’s build() method takes a BuildContext as an argument. The build context tells you where you are in the tree of widgets. You can access the element for any widget through the BuildContext. Later, you’ll see why the build context is important, especially for accessing state information from parent widgets.

Adding stateful widgets

Card2 is currently a StatelessWidget. Notice that the Heart button on the top-right currently does nothing. This isn’t because you haven’t hooked up any actions. It’s because the widget, as it is, can’t manage state dynamically. To fix this, you’ll change this card into a StatefulWidget.

class AuthorCard extends StatefulWidget {
  ...

  @override
  _AuthorCardState createState() => _AuthorCardState();
}

class _AuthorCardState extends State<AuthorCard> {
  @override
  Widget build(BuildContext context) {
    ...
  }

Implementing favorites

In _AuthorCardState, add the following property right after the class declaration:

bool _isFavorited = false;
IconButton(
  // 1
  icon: Icon(_isFavorited ? Icons.favorite : Icons.favorite_border),
  iconSize: 30,
  // 2
  color: Colors.red[400],
  onPressed: () {
    // 3
    setState(() {
      _isFavorited = !_isFavorited;
    });
  },
)

Examining the widget tree

Now that you’ve turned AuthorCard into a stateful widget, your next step is to look at how the element tree manages the changes in state.

Inherited widgets

Inherited widgets let you access state information from the parent elements in the tree hierarchy.

Key points

  • Flutter maintains three trees in parallel: the Widget, Element and RenderObject trees.
  • A Flutter app is performant because it maintains its structure and only updates the widgets that need redrawing.
  • The DevTools Flutter Inspector is a useful tool to debug, experiment with and inspect a widget tree.
  • You should always start by creating StatelessWidgets and only use StatefulWidgets when you need to manage and maintain the state of your widget.
  • Inherited widgets are a good solution to access state from the top of the tree.

Where to go from here?

If you want to learn more theory about how widgets work, check out the following links:

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.

Unlock now