Flutter Course: 9.2 Stateless Widget

Hello! In this tutorial, we will take a deep dive into Flutter’s Stateless widgets. Stateless widgets are one of the most fundamental components in Flutter, as they do not hold any state and always provide the same output given the same input. Due to this characteristic, Stateless widgets are very useful in constructing UIs and are efficient and customizable.

Overview of Stateless Widgets

Stateless widgets are used when the data does not change or does not need to change. In other words, these widgets do not store state and always display the same information. These widgets have the following characteristics:

  • Immutability: Once a Stateless widget is created, its data cannot be changed.
  • Efficiency: Since there is no need to manage state, this widget is lighter and more efficient.
  • Simple Reusability: They can be easily reused as they always provide the same output with the same data.

Using Stateless widgets to construct the UI of a Flutter application is simple and intuitive. Now, let’s learn how to create and use Stateless widgets.

Structure of Stateless Widgets

Stateless widgets are created by inheriting from the StatelessWidget class in Flutter. This class overrides the build method to define how the widget will be constructed.

Example of a Stateless Widget

Here is an example of using a basic Stateless widget:

import 'package:flutter/material.dart';

class MyStatelessWidget extends StatelessWidget {
  final String title;

  MyStatelessWidget({Key key, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(16.0),
      child: Text(
        title,
        style: TextStyle(fontSize: 24),
      ),
    );
  }
}

The above code creates a simple Stateless widget. This widget takes a title parameter and displays it as a Text widget. The build method determines how Flutter visually represents the widget.

Advantages of Stateless Widgets

Using Stateless widgets offers several advantages:

  • Performance: You can avoid unnecessary state management, which improves the app’s performance.
  • Simplicity: This widget is easy to use and has a simple structure.
  • Flexibility: It can be easily integrated into various functional programming styles.

Stateless Widgets vs. Stateful Widgets

The two main types of widgets in Flutter are Stateless widgets and Stateful widgets. Stateless widgets do not hold any state, while Stateful widgets maintain state. To understand this, let’s compare them with a simple example.

Example of a Stateful Widget

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

class _MyStatefulWidgetState extends State {
  int counter = 0;

  void incrementCounter() {
    setState(() {
      counter++;
    });
  }

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

The above Stateful widget increments the value of the counter every time the button is clicked. It updates the state by calling the setState method, which causes the widget to rebuild. In contrast, Stateless widgets cannot change state, so there is no change.

Use Cases for Stateless Widgets

Stateless widgets are primarily used in the following cases:

  • Displaying simple information: text, icons, etc.
  • Creating static layouts: structuring the layout of widgets when no state is needed
  • Combining various UI components: buttons, cards, etc.

Styling in Stateless Widgets

When constructing a UI using Stateless widgets, it is important to understand how to set styles and layouts. In Flutter, you can apply various styling and layouts using widgets like Container, Row, and Column.

Styling Example

class StyledWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.all(20),
      padding: EdgeInsets.all(10),
      decoration: BoxDecoration(
        color: Colors.blue,
        borderRadius: BorderRadius.circular(10),
      ),
      child: Text(
        'Styled Container',
        style: TextStyle(color: Colors.white, fontSize: 20),
      ),
    );
  }
}

In the example above, the Container widget is used to set the background color, margin, padding, and border radius. This creates a styled widget.

Refactoring with Stateless Widgets

Utilizing Stateless widgets can enhance the readability of your code and make maintaining it easier. It is important to refactor Stateless widgets well to increase code reusability, and here are some methods:

  • Widgetize: To prevent code duplication, you can separate Stateless widgets into functions based on functionality.
  • Use Composition: Combine multiple Stateless widgets to create more complex UIs.
  • Clear Naming: Assign appropriate names to widgets to make their purposes clear.

Building an Application Using Stateless Widgets

Now, let’s create a simple Flutter application using Stateless widgets. This application will primarily have a feature to input the user’s name and display that name prominently on the screen.

Application Example Code

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Stateless Widget Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final TextEditingController _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Stateless Widget Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: _controller,
              decoration: InputDecoration(labelText: 'Enter your name'),
            ),
            ElevatedButton(
              child: Text('Show Name'),
              onPressed: () {
                final name = _controller.text;
                showDialog(
                  context: context,
                  builder: (BuildContext context) {
                    return AlertDialog(
                      title: Text('Hello, $name!'),
                      actions: [
                        TextButton(
                          child: Text('Close'),
                          onPressed: () {
                            Navigator.of(context).pop();
                          },
                        ),
                      ],
                    );
                  },
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

The above code creates a basic Flutter application that allows the user to input their name and displays that name in a dialog upon pressing a button. In this example, TextField and ElevatedButton are used to define a simple UI, and Stateless widgets are constructed to respond to user input.

Conclusion

In this tutorial, we have thoroughly explored Flutter’s Stateless widgets. Stateless widgets are powerful tools that can construct UIs efficiently and concisely. By using these widgets when data does not change, you can improve performance and clarify the structure of your code. Leverage Stateless widgets in various scenarios to make your Flutter applications more attractive and functional.

Thank you!