Mastering Dart Extension Methods in Flutter: A Comprehensive Guide

25 Jun 2023 By Christian Findlay
Build App Icon

Christian is the Director of Nimblesite

Nimblesite specializes in building and maintaining Flutter apps. Call Nimblesite in Australia on 1300 794 205 to hire an expert.

HIRE A FLUTTER EXPERT

Dart has a powerful feature called extensions. This feature can significantly improve the readability and maintainability of your Flutter code. This comprehensive tutorial explores how to use Dart extension methods and properties (members) to enhance your Flutter code, with a particular focus on widget composition.

What are Dart Extension Methods in Flutter?

Extension Methods were introduced in Dart 2.7. Dart extension methods allow developers to add new functionality to existing classes. This means you can add members (methods or getters etc.) to any class, including classes from the Dart core libraries, without creating a subclass or changing the original class. This feature is incredibly powerful and can make your Flutter code cleaner and more intuitive.

Using Dart Extensions for Widget Composition in Flutter

Widget composition is a fundamental concept in Flutter. It involves combining smaller, simpler widgets to create more complex widgets. However, nesting can make code harder to read and often becomes very verbose. You can create a Dart extension method on the Widget class instead of writing the same code repeatedly. Here is a padding example. You can use the pad() method on any widget.

Padding

extension PaddingExtension on Widget {
  Widget pad([double value = 8.0]) => Padding(
        padding: EdgeInsets.all(value),
        child: this,
      );
}

Notice that you can also specify a default value so that your widgets get consistent spacing etc. by default.

Rounded Borders

Rounded borders are common in Flutter apps. You can create a roundedBorder() extension method on the Widget class to make your code more readable.

extension BorderExtension on Widget {
  Widget roundedBorder(
      {double radius = 10.0, Color color = Colors.black, double width = 1.0}) {
    return Container(
      decoration: BoxDecoration(
        border: Border.all(color: color, width: width),
        borderRadius: BorderRadius.circular(radius),
      ),
      child: this,
    );
  }
}

Here is an example of how to use it

void main() => runApp(MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: Scaffold(
          body: const Text('Hello World!')
              .roundedBorder(radius: 15.0, color: Colors.blue, width: 2.0)),
    ));

Any number of composition tasks can be made more succinct with extension methods.

BuildContext Shortcuts with Dart Extensions

Extension methods can help you access TextStyles, perform navigation, or even pop up a dialog. You can create a Dart extension method on the BuildContext class to access these items

Theme Shortcuts

Here is an example extension that accesses a TextStyle as part of the Theme. This approach makes your code more maintainable. If you want to switch to a different TextStyle, you only need to change the code in one place.

extension ThemeExtensions on BuildContext {
  TextStyle get bodyLarge => Theme.of(this).textTheme.bodyLarge!;
}

Notice that this extension is technically not a method. It’s a property getter. You don’t need to supply arguments. This is how can you use the extension:

@override
Widget build(BuildContext context) => MaterialApp(
    home: Scaffold(
      body: Center(
        child: Text('Hello World!', style: context.bodyLarge),
      ),
    ),
  );

You can use extension methods to show popup dialogs, bottom sheets, or snackbars. This extension displays a snackbar.

void showSnackbar(String message) => ScaffoldMessenger.of(this).showSnackBar(
      SnackBar(content: Text(message)),
    );

This is how you use the extension:

void main() {
  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,
      scaffoldMessengerKey: GlobalKey<ScaffoldMessengerState>(),
      home: Builder(
        builder: (context) => Scaffold(
          body: Center(
            child: ElevatedButton(
                onPressed: () => context.showSnackbar('Here is your snack!'),
                child: const Text('Snack')),
          ),
        ),
      ),
    ),
  );
}

You can also use extension methods to navigate to a new screen. This extension navigates to a new screen by route name.

extension NavigationExtension on BuildContext {
  Future<void> navigateTo(String routeName, {Object? arguments}) {
    return Navigator.pushNamed(this, routeName, arguments: arguments);
  }
}

Here is a full live demo that uses the extension

Conclusion

Dart extension members are a powerful tool that can significantly improve your Flutter code. They allow you to add new functionality to existing classes and reduce the amount of code you need to write. This leads to a more maintainable and readable codebase.