Dart Extensions methods for Flutter

Extension methods are added to the classes of existing libraries, which we cannot directly modify, to add additional functionalities. Dart 2.7, introduced extension methods. Extensions can not only consist of methods, but also getters, setters and operators.

We implement extension methods with the syntax:

extension <extension_name> on <type> {
  (<member definition>)*
}

Generally, when we want to have custom functionalities on a certain class, we would create a Utility class. It would look like this:

class Utility{
  static String doSomething(String s){
    return "$s something";
  }
}

And invoked like this:

String formattedString = Utility.doSomething("value");

Now, there is no harm in using static methods from Utility class but Utility class tends to breach the principle of Object-oriented programming and the class also usually consists of lots of unrelated static methods and code organization becomes messy. Hence, extension methods may be the way to go.

Implementation of Extension method

extension StringExtension on String{
  bool isValidEmail(){
    return RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~][email protected][a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(this);
  }
}

String email = "[email protected]";
print(email.isValidEmail()); // prints true

See, how convenient it is to call the extension method, just like how you would invoke an object’s method.

We can also use extensions to give custom functionalities to flutter widgets. Let us create a file named extensions.dart and define an extension method inside the file.

import 'package:flutter/material.dart';

extension String_Url_Extension on String{
  circleImage(){
    return CircleAvatar(
      backgroundColor: Colors.greenAccent,
      radius: 60,
      backgroundImage: NetworkImage(this),
    );
  }
}

We have applied the extension on String object and inside a method named circleImage(). This method displays the image in circular avatar on whichever URL string we invoke it upon.

Now, in the main.dart file, let us code the UI part in main.dart where we invoke the above extension method.

import 'package:flutter/material.dart';
import 'extensions.dart';

void main() => runApp(MyApp());

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

class ExtensionDemo extends StatelessWidget {
  const ExtensionDemo({Key? key}) : super(key: key);

  final imageUrl =
      "https://image.shutterstock.com/image-vector/panoramic-countryside-landscape-autumn-fallen-260nw-1174405507.jpg";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 0,
        title: Text("Demo"),
      ),
      body: Center(
        child: imageUrl.circleImage(),
      ),
    );
  }
}

Across the application, if you want to display any image from the network in circle avatar, just invoke the method circleImage() on the URL and you get the job done. No need to wrap the image in multiple widgets every time you want to implement this.

Implementation of above extension method

I hope this article helped you understand the usefulness of dart extension methods and where to apply them.

If you are learning Dart. Here is the helpful guide on Getting started with Dart.