FlutterGen Code Generation

FlutterGen Code Generation

Good-bye Typos!

One of the most important programming principles I've heard since my freshman year of college is DRY, or Don't Repeat Yourself.

DRY gives us a way to solve problems through code that applies to almost any problem. It is even a way of applying algorithms in our daily lives.

Do not repeat yourself, if you do, there is room for optimization. From a technical point of view, this principle urges us to automate a repetitive process that, at first suggests the implementation of a loop such as for or while as a solution. Or write a script that runs that action that takes us more time and effort than we would like.

There is a type of super useful tool when we're programming, the famous code-gen or code generators. They consist of a program that is incorporated into our project to run in development and create files with all the settings that would have lengthened development time.

Why?

Before getting into business, I would like to show you a typical problem where we can see the reason for these programs.

Image imageFile = Image.asset('assets/img/my_image.png');

In this case, we are declaring an image that is initialized as an asset that we loaded from the same project. To assign this asset, we must provide the path of the .png file to the method. This is not safe because we are human beings and we tend to make errors (typos) that may not be detected by a linter or compiler.

In short, code generation handles these problems as it is responsible for writing the code that we need so that we can use it and we can identify/correct errors more easily.

Now that we know that, let's use these utilities.

⚠️ Disclaimer: 95% of the time I find myself writing Dart code, so this article will be focused on how we can be more efficient when programming apps with Flutter, using code generation tools.

How?

FlutterGen is a relatively new code generator, it takes care of many of the big problems when working with local files, specifically resources that our apps use for branding (the logo, for example).

Well, a good practice is to always store the values that are used many times in the app in variables and classes.

We can move on from this:

Future callToAPI() async {
    await http.get('url_to_my_api.dev/api');
}

Future anotherCallToAPI() async {
    await http.get('url_to_my_api.dev/api/another');
}

To this:

class API {
    static const url = 'url_to_my_api.dev/api';
}

Future callToAPI() async {
    await http.get(API.url);
}

Future anotherCallToAPI() async {
    await http.get('${API.url}/other');
}

A very simple way of only accessing the url property of the API class and that way we can use the same variable in other parts of our app. It is also easier if we change the string that contains url since it would be changed in all the parts where we use it.

Setup

To use FlutterGen, we need to configure it. We have 3 options:

  • Homebrew.
brew install FlutterGen/tap/fluttergen
  • Pub.
dart pub global activate flutter_gen
  • build_runner. With Dart's build system there are usually some versioning conflicts between packages, so let's skip that for now.

My suggestion, use Pub. You will have to update your PATH at the end of the installation, running the following command in the terminal:

export PATH ="$PATH":"$HOME/.pub-cache/bin"

Next, we must do the pubspec.yaml configuration. At this point, we must have assets included in the pubspec. Here is what you can copy and paste at the end of your file, the explanation goes in the comments.

# here goes all the config for flutter_gen
# watch out for the indentations
flutter_gen:
    # by default, the generate files are in `lib/gen/`
    # you can set other directories like `lib/src/gen` using [output]
  output: lib/src/gen/

    # if you use some linter that is line-of-code-sensitive
    # you can satisfy the lines it demands with [lineLength]
    # the default value is 80
  lineLength: 90

  # integrations are optional if you use another 3rd party
    # package, like [flutter_svg] to use .svg files like we
    # do with fonts and images
    #
    # it's important to have your integrations as project dependencies
  integrations:
    flutter_svg: true

    # you can also add color files in XML format
    # if you're reusing from an android project
  colors:
    inputs:
      - assets/color/colors.xml

Ok, that was all the configuration we had to do. Now let's see the magic.

Generation and usage

We run the command:

fluttergen -c pubspec.yaml

Taking into consideration that the path to the pubspec may vary and must be checked in the case of getting an error. If all goes well, you will have a new gen/ folder in the path you specified in the pubspec.

Now we are going to use the generated code. In the case of images, we access through Assets, until we reach the one we're going to use. Since our image becomes an Image object, then it is not necessary to wrap it in the widget, we just call the image() method:

Assets.images.background.image();

If we need text fonts, we have a class called FontFamily, where we have as properties the text strings that contain the identifiers of our fonts. We use them like this:

Text(
  'We\'re using fonts generated by FlutterGen',
  style: TextStyle(fontFamily: FontFamily.googleSans),
);

Finally, in order not to leave you without the example of the colors (in case someone uses them that way), we have a class called ColorName that allows us to access them.

Container(height: 100, width: 100, color: ColorName.justBlack);

Now we have our generated code and we know how to use it, we just have to start implementing it in our apps.

If you have any questions regarding this package, in this link you can browse the documentation and you can also check its source code in its repo from GitHub.