Introduction to Widgets


Introduction to Widgets Interview with follow-up questions

1. What are the two types of widgets in Flutter?

The two are StatelessWidget and StatefulWidget.

  • StatelessWidget — has no mutable state; given the same inputs it always builds the same UI (e.g. Icon, Text).
  • StatefulWidget — pairs with a separate State object that holds mutable state; calling setState() triggers a rebuild (e.g. a checkbox, a form, a counter).

A sharp follow-up: even a StatefulWidget is itself immutable — the mutable data lives in its State. And InheritedWidget is a third, more specialized kind used to propagate data down the tree (it backs Theme, MediaQuery, and Provider).

↑ Back to top

Follow-up 1

What is the difference between Stateless and Stateful widgets?

Stateless widgets are immutable, meaning their properties cannot change once they are created. They are used for displaying static content. Stateful widgets, on the other hand, are mutable and can change their properties over time. They are used for displaying dynamic content that can be updated.

Follow-up 2

Can you give an example of each type?

Sure! Here's an example of a Stateless widget:

class MyStatelessWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text('Hello, World!'),
    );
  }
}

And here's an example of a Stateful widget:

class MyStatefulWidget extends StatefulWidget {
  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State {
  int counter = 0;

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: [
          Text('Counter: $counter'),
          RaisedButton(
            child: Text('Increment'),
            onPressed: () {
              setState(() {
                counter++;
              });
            },
          ),
        ],
      ),
    );
  }
}

Follow-up 3

How do you decide which type of widget to use?

You should use a Stateless widget when the content you want to display does not change over time. This is useful for displaying static text, images, or icons. On the other hand, you should use a Stateful widget when the content you want to display can change over time, such as a counter or a form input. Stateful widgets allow you to update their properties and re-render the UI when needed.

2. What is the purpose of widgets in Flutter?

Widgets are the building blocks of a Flutter UI — in Flutter, everything is a widget. Their purpose is to declaratively describe what the UI should look like for a given state: structure and layout (Row, Column, Padding), visual elements (Text, Image, buttons), and behavior (gesture/input handling). Each widget is an immutable configuration object; you compose and nest them into a tree to build complex screens from small reusable pieces. When state changes, you rebuild the affected widgets and Flutter efficiently diffs the tree to update only what changed. The key idea to convey: widgets are a description of the UI, not the rendered pixels — Flutter turns them into Elements and RenderObjects to actually lay out and paint.

↑ Back to top

Follow-up 1

How do widgets contribute to the UI of a Flutter application?

Widgets contribute to the UI of a Flutter application by defining the visual elements and layout. Each widget represents a specific UI component and can be customized with properties and attributes. Widgets can be combined and nested to create complex UI designs. They can also be updated dynamically to reflect changes in the application state. Flutter provides a rich set of pre-built widgets that can be used out of the box, and also allows developers to create their own custom widgets.

Follow-up 2

Can a Flutter application be built without widgets?

No, a Flutter application cannot be built without widgets. Widgets are fundamental to the Flutter framework and are required to define the UI components and layout. Every visual element in a Flutter application is represented by a widget. Even the simplest UI elements, such as text or images, are implemented as widgets. Widgets provide the necessary structure and behavior to create a responsive and interactive user interface.

Follow-up 3

What happens if a widget is removed from the widget tree?

If a widget is removed from the widget tree in Flutter, it will no longer be rendered on the screen. The widget and its associated UI components will be unmounted and disposed. Any state associated with the widget will be lost. If the removed widget had any child widgets, they will also be removed from the widget tree. Removing a widget from the widget tree can be done dynamically to update the UI based on user actions or application state changes.

3. How does Flutter use widgets to build the UI?

Flutter builds the UI by composing widgets into a tree, declaratively. You write a root widget whose build method returns child widgets, each of which builds its own children, and so on — Flutter walks this tree to construct the UI. Because widgets are immutable descriptions, when state changes Flutter rebuilds the affected subtree and efficiently diffs it (via the Element tree) to update only what actually changed.

Here's a minimal widget tree:

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('My App')),
        body: const Center(child: Text('Hello, World!')),
      ),
    );
  }
}

The detail interviewers like: this is the Widget tree (configuration). Flutter inflates it into an Element tree (lifecycle/state, links widgets to render objects) and a RenderObject tree (actual layout and painting). Layout flows constraints down and sizes up, which is why understanding BoxConstraints matters when widgets don't size as expected.

↑ Back to top

Follow-up 1

What is the widget tree?

The widget tree is a hierarchical structure in Flutter that represents the user interface of an application. It is composed of widgets, which are the building blocks of the UI. Each widget in the tree represents a specific part of the UI, such as a button, a text field, or a layout.

The widget tree is created and assembled by Flutter based on the code written by the developer. It starts with a root widget, usually the MaterialApp widget, and recursively builds the tree by creating and assembling child widgets.

The widget tree is important because it defines the structure and appearance of the UI. It determines how the UI is rendered on the screen and how it responds to user interactions and events.

Here's an example of a simple widget tree in Flutter:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('My App'),
        ),
        body: Center(
          child: Text('Hello, World!'),
        ),
      ),
    );
  }
}

Follow-up 2

How does Flutter render widgets on the screen?

Flutter renders widgets on the screen using a process called the "reconciliation". When the widget tree is built, Flutter compares the new widget tree with the previous widget tree and determines the differences between them.

Based on these differences, Flutter updates the UI by adding, removing, or modifying the widgets on the screen. This process is efficient because Flutter only updates the parts of the UI that have changed, instead of rebuilding the entire UI.

To render widgets on the screen, Flutter uses a rendering engine called Skia. Skia is a cross-platform 2D graphics library that provides low-level rendering capabilities. It allows Flutter to draw and manipulate widgets, apply animations and effects, and handle user interactions.

Here's an example of how Flutter renders widgets on the screen:

  1. Flutter builds the widget tree based on the code written by the developer.
  2. Flutter compares the new widget tree with the previous widget tree to determine the differences.
  3. Flutter updates the UI by adding, removing, or modifying the widgets on the screen.
  4. Flutter uses Skia to render the updated widgets and display them on the screen.

Follow-up 3

What is the role of the BuildContext in the widget tree?

The BuildContext is an important concept in Flutter that represents the location of a widget in the widget tree. It provides access to various information and services related to the widget and its position in the tree.

The BuildContext is used in several ways in the widget tree:

  1. Building the UI: When a widget's build() method is called, it receives a BuildContext as a parameter. The widget can use this context to access the properties and methods of its parent widget, such as the theme, the media query, or the localization.

  2. Widget creation: When creating child widgets, the parent widget passes its own BuildContext to the child widget's constructor. This allows the child widget to access the properties and methods of its parent widget.

  3. Inherited widgets: The BuildContext is used to access inherited widgets, which are widgets that provide data or services to their descendants in the widget tree. Inherited widgets are useful for sharing data across multiple widgets without passing it explicitly through the widget constructors.

Here's an example of how the BuildContext is used in the widget tree:

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Theme.of(context).primaryColor,
      child: Text(
        'Hello, World!',
        style: TextStyle(
          color: Theme.of(context).textTheme.bodyText1.color,
        ),
      ),
    );
  }
}

4. What is the lifecycle of a widget in Flutter?

It depends on the widget type. A StatelessWidget has a trivial lifecycle — it's constructed and its build runs whenever its inputs change. The lifecycle question is really about a StatefulWidget's State object, which interviewers expect you to recite in order:

  1. createState() — the StatefulWidget creates its State.
  2. initState() — called once; initialize controllers, subscriptions, animations.
  3. didChangeDependencies() — called after initState and whenever an inherited dependency (e.g. Theme, MediaQuery, a Provider) changes.
  4. build() — returns the UI; runs on every rebuild.
  5. didUpdateWidget(old) — called when the parent rebuilds with a new widget configuration; react to changed properties here.
  6. setState() — request a rebuild after mutating state.
  7. deactivate() — the element is removed from the tree (may be reinserted).
  8. dispose() — called once when permanently removed; clean up here (dispose controllers, cancel timers/streams) to avoid leaks.

The two gotchas to flag: don't call setState in initState/dispose, and always release resources in dispose — forgetting to is the most common Flutter memory leak.

↑ Back to top

Follow-up 1

What happens when a widget is created?

When a widget is created, the framework calls the createState() method of the widget, which creates a new instance of the widget's associated State class. The State object is then associated with the widget and becomes the widget's current state. The initState() method of the State class is called, allowing the widget to initialize any necessary data or resources.

Follow-up 2

What happens when a widget's state changes?

When a widget's state changes, the framework calls the build() method of the widget's associated State class. The build() method returns a new widget tree, which is then compared to the previous widget tree. The framework then updates the user interface to reflect the changes in the widget tree. Additionally, the didUpdateWidget() method of the State class is called, allowing the widget to handle any specific logic related to the state change.

Follow-up 3

What happens when a widget is destroyed?

When a widget is destroyed, the framework calls the dispose() method of the widget's associated State class. The dispose() method allows the widget to release any resources or clean up any subscriptions before the widget is removed from the widget tree. This is typically used to unsubscribe from streams, cancel animations, or release any other resources that were allocated during the widget's lifecycle.

5. Can you explain how to create a custom widget in Flutter?

To create a custom widget, extend StatelessWidget or StatefulWidget and implement build:

  1. Create a Dart file for the widget (in lib/).
  2. Import package:flutter/material.dart.
  3. Define a class extending StatelessWidget (no internal state) or StatefulWidget (needs mutable state).
  4. Expose configuration via final fields set through a const constructor (and always accept a Key).
  5. Implement build to return the UI, composing existing widgets.
  6. Use it by instantiating it anywhere in the tree.

Here's a reusable CustomButton:

import 'package:flutter/material.dart';

class CustomButton extends StatelessWidget {
  const CustomButton({super.key, required this.label, required this.onPressed});

  final String label;
  final VoidCallback onPressed;

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: onPressed,
      child: Text(label),
    );
  }
}

Two modern points interviewers look for: prefer composition over inheritance (build from existing widgets rather than subclassing them), and make widgets const-constructible with final fields where possible — const widgets are skipped during rebuilds, which improves performance. (Note: the old RaisedButton was removed years ago; use ElevatedButton.)

↑ Back to top

Follow-up 1

What are the steps to create a custom widget?

The steps to create a custom widget in Flutter are as follows:

  1. Create a new Dart file for your custom widget.
  2. Import the necessary packages and dependencies.
  3. Define a class that extends the StatelessWidget or StatefulWidget class.
  4. Implement the build method to return the UI representation of your widget.
  5. Optionally, add any additional properties or methods to customize the behavior of your widget.
  6. Use your custom widget in your app by instantiating it and adding it to the widget tree.

Here's an example of a custom widget called CustomButton:

import 'package:flutter/material.dart';

class CustomButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      onPressed: () {},
      child: Text('Custom Button'),
    );
  }
}

Follow-up 2

What are the considerations when creating a custom widget?

When creating a custom widget in Flutter, there are a few considerations to keep in mind:

  1. Reusability: Design your widget to be reusable in different parts of your app.
  2. Composition: Break down complex UI elements into smaller, reusable widgets.
  3. Encapsulation: Hide the internal implementation details of your widget and expose only the necessary properties and methods.
  4. Performance: Optimize your widget's performance by minimizing unnecessary rebuilds and using efficient rendering techniques.
  5. Documentation: Provide clear and concise documentation for your custom widget to make it easier for other developers to understand and use.

By following these considerations, you can create custom widgets that are flexible, maintainable, and easy to use.

Follow-up 3

Can you give an example of a situation where a custom widget would be useful?

A custom widget can be useful in various situations, such as:

  1. Creating a specialized UI component that is not available in the default Flutter widget library.
  2. Abstracting complex UI logic into a reusable widget to improve code organization and maintainability.
  3. Customizing the appearance and behavior of existing Flutter widgets to match specific design requirements.
  4. Creating a widget that encapsulates a specific functionality or interaction pattern that is used in multiple places within an app.

For example, you might create a custom widget called AnimatedProgressBar that animates a progress bar based on a given value. This widget can be used in different parts of your app to display progress indicators with custom animations.

Live mock interview

Mock interview: Introduction to Widgets

Intermediate ~5 min Your own free AI key

Your voice and your AI key never touch our servers; the key stays in this browser and is sent only to Google. Only your round scores are saved to track progress.