Skip to main content

Creating flutter packages

 

How to create Dart packages for Flutter


In Flutter, we use the Dart programming language to build cross-platform applications. Dart packages are like the libraries you might be used to installing for, say, Node.js projects using either npm or yarn. These packages are built by Flutter devs for Flutter devs.

In this tutorial, we’ll show you how to build Dart packages and share them with other Flutter developers around the world.

We’ll cover the following with practical examples:

  • What is a Dart package?
  • Flutter project requirements
  • Dart package types
  • Creating a Flutter/Dart package
  • Initializing a Git repo
  • Writing a Flutter widget
  • Testing your Flutter package
  • Publishing and sharing your Flutter package

What is a Dart package?

Dart packages help us solve issues and create workarounds for problems without having to write the code ourselves from scratch.

For example, let’s say we’re building a Flutter app and we discover that we need to upload a picture from our local filesystem and display it in the app. Implementing that ourselves would be tedious and time-consuming.

Chances are, some developer somewhere has already built a Dart package for Flutter to handle the image picking and display functionalities for us. All we have to do is install the package, then use its methods and classes to find and display images. This affords us more time to focus on the core business logic of our app.

Flutter project requirements

To follow along with this tutorial, make sure you have the Flutter SDK installed on your machine.

The Flutter SDK is used to build, compile, and run Flutter projects. To install it, head to the official Flutter website and download the appropriate SDK depending on your operating system:


Dart package types

There are two types of packages in Dart: regular Dart packages and plugin packages.

  • Dart packages are general packages written in Dart. They are independent of any native platforms, such as Android and iOS. These packages are Flutter-specific and can only be used on the Flutter framework
  • Plugin packages are platform-specific and contain APIs written in Dart code. These packages can be written for Android (using Kotlin or Java), iOS (using Swift or Objective-C), web, macOS, Windows, or Linux

In this tutorial, we’ll demonstrate how to create a Dart package.


Creating a Flutter/Dart package

To create a Flutter package, run the below command:

flutter create --template=package flutter_pkg
  • The create subcommand is used to create a Flutter project or package. In this case, it will create a Flutter package
  • The --template=package flag tells it to create a Flutter package
  • The flutter_pkg is the folder in which the Flutter package will be created. You can name it anything you want

The command will run like this:

Creating project flutter_pkg...
  flutter_pkg/LICENSE (created)
  flutter_pkg/test/flutter_pkg_test.dart (created)
  flutter_pkg/flutter_pkg.iml (created)
  flutter_pkg/.gitignore (created)
  flutter_pkg/.metadata (created)
  flutter_pkg/pubspec.yaml (created)
  flutter_pkg/README.md (created)
  flutter_pkg/lib/flutter_pkg.dart (created)
  flutter_pkg/.idea/libraries/Dart_SDK.xml (created)
  flutter_pkg/.idea/modules.xml (created)
  flutter_pkg/.idea/workspace.xml (created)
  flutter_pkg/CHANGELOG.md (created)
Running "flutter pub get" in flutter_pkg...                         5.3s
Wrote 12 files.

All done!
Your package code is in flutter_pkg/lib/flutter_pkg.dart

The main file, or the entry file, of this package, is lib/flutter_pkg.dart. Flutter sets the main file to be the same as the package name with the .dart extension. Our package name is flutter_pkg, so the main file will be flutter_pkg.dart. If the package name is modalpicker, the main file will be modalpicker.dart.

Let’s look at some of the files and folders we generated to learn what each of them does.

  • pubspec.yaml contains the information regarding a Flutter package as well as dependencies for that project. It also enables us to specify the assets we want to add to our Flutter project, such as images, fonts, etc.
  • .gitignore tells Git which files in our Flutter project to ignore when pushing our code to a repository
  • README.md contains general information about the project written in Markdown. This file describes how to install, run, and contribute to the project, among other things
  • CHANGELOG.md is where we add changes that were made to the project. This document is also written in Markdown

Initializing a Git repo

Before we proceed further, we need to initialize a Git repo in our project. This helps when we need to push our package to pub.dev.

Run the below code:

echo "# flutter_pkg" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:flutter-prjs/flutter_pkg.git
git push -u origin main

We will include a homepage or repository field in our pubspec.yaml. In the homepage, we’ll add the Git repo URL of our package project. We’ll also add a description to clearly describe to devs what this package does.

name: flutter_pkg
description: A new Flutter package with a customized TextButton.
version: 0.0.1
author: Chidume Nnamdi
homepage: https://github.com/flutter-prjs/flutter_pkg

Writing a Flutter widget

Next, we’ll create a custom button styled to our liking.

Clear the original code generated by Flutter in the lib/flutter_pkg.dart. Then, add the CustomButton widget:

library flutter_pkg;

import 'package:flutter/material.dart';

class CustomButton extends StatelessWidget {
  var onPressed;
  final Widget child;
  var style;
  CustomButton({Key key, @required this.onPressed, this.child, this.style})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return TextButton(
      onPressed: onPressed,
      style: TextButton.styleFrom(
        padding: const EdgeInsets.all(16.0),
        primary: Colors.white,
        backgroundColor: Colors.blue,
        elevation: 9.0,
        textStyle: const TextStyle(
          fontSize: 20,
        ),
      ),
      child: child
    );
  }
}

The library flutter_pkg code sets the name of our package to flutter_pkg.

First, we imported the Flutter Material package — this is the root of all Flutter apps. Next, we created a CustomButton class that extends the StatelessWidget class. This causes our CustomButton widget to hold or manage no local state.

We have three properties that the CustomButton widget constructor will receive:

  • onPressed — This function will be called when the CustomButton widget is pressed or clicked
  • style — This property will hold the custom styling of the button from its users. The users might decide to style our CustomButton widget to their taste, so they code the styling and pass it down to the CustomButton widget via the style property
  • child — This is a widget tree of the CustomButton widget. This tree is usually a Text widget that displays the text on the button

The build method renders a TextButton and styles the button as follows:

  • padding — The padding is set to 16.0 units all sides
  • primary — The primary color of the button is set to blue
  • backgroundColor — The background color of the button is set to blue
  • elevation — The box shadow of the button is elevated to 9.0 units
  • textStyle — The font size is set to 20 units to make the button appear much bigger
  • child — This property renders the widget tree of the CustomButton widget

Our custom button is something like a smaller version of TextButton. This button renders a customized TextButton. Inside our CustomButton, we increased the padding, elevation, background color, and text style of the TextButton.

To use this widget, enter the following:

CustomButton(
    onPressed: _incrementCounter,
    child: const Text("Click me")
),

Testing your Flutter package

We will need to test our package to see if it is working. To do that, we have to create a Flutter project in our project:

flutter create example

An example folder will be created in our flutter_pkg project.

Next, we have to install our flutter_pkg in the example Flutter project. Since the package is not yet published to pub.dev, we will refer to the path locally.

Open pubspec.yaml in the example project, and add this line:

dependencies:
  flutter:
    sdk: flutter
  flutter_pkg:
    path: ../

The path: ../ tells Flutter to get the flutter_pkg dependency from the path ../ — that is, from its parent folder.

Open lib/main.dart and add the following code to the _MyHomePageState widget:

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            CustomButton(
              onPressed: _incrementCounter,
              child: const Text("Click me")
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

We imported the flutter_pkg package, then we set the CustomButton widget between two Text widgets.

Run the example project by running flutter run in the command line.


Great! Our package is completed. Now we can publish it to pub.dev so other developers can use our package.

Publishing and sharing your Flutter package

Now that we know our Dart package is working, we can now publish it to pub.dev so other developers can use our package.

Before we publish our package, let’s add a license to the LICENSE file:

Copyright (c) 2021 Chidume Nnamdi
Permission is hereby granted to use this software as deemed fit.

Next, we’ll push our changes to Git. Run the below code:

git add . && git commit -m "Made some changes" && git push

Now it’s time to publish our package:

flutter packages pub publish

Something like this will appear:

Publishing flutter_pkg 0.0.1 to https://pub.flutter-io.cn:
|-- .gitignore
|-- .metadata
|-- CHANGELOG.md
|-- LICENSE
|-- README.md
|-- example
...

At the bottom, it will require authorization if you are not yet authorized on pub.dev.

Pub needs your authorization to upload packages on your behalf.
In a web browser, go to https://accounts.google.com/o/oauth2/auth?access_type=offline&...wpFwBAMgkc&code_challenge_method=S256&scope=openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email
Then click "Allow access".

Waiting for your authorization...

Then you will have to click on the link in the terminal above. Finally, you will be prompted to authorize access via your selected Gmail account.

Conclusion

We started by introducing packages in Dart, what they are, and how they are designed to share code with other devs.

Later on, we learned how to scaffold a Flutter package project and how to write the package code. Next, we learned how to test our Flutter package locally and, finally, how to publish our Flutter package to pub.dev.





Comments

Popular posts from this blog

GSoC Final Report

GSoC Final Report My journey on the Google Summer of Code project passed by so fast, A lot of stuff happened during those three months, and as I’m writing this blog post, I feel quite nostalgic about these three months. GSoC was indeed a fantastic experience. It gave me an opportunity to grow as a developer in an open source community and I believe that I ended up GSoC with a better understanding of what open source is. I learned more about the community, how to communicate with them, and who are the actors in this workflow. So, this is a summary report of all my journey at GSoC 2022. Name : Ansh Dassani Organization:   NumFOCUS- Data Retriever Project title : Training and Evaluation of model on various resolutions Project link:  DeepForest Mentors :  Ben Weinstein ,  Henry Senyondo , Ethan White Introduction                                        DeepForest is a python package for training and predicting individual tree crowns from airborne RGB imagery. DeepForest comes with a prebuil

GSOC Project

DeepForest This project aims to make the model which would already be trained for the classification of species and detection of alive and dead, trees or birds using transfer learning on the current release model which is based on object detection, only detecting trees and birds, for now, It also involves improving the user interface for working with the multi-class model for a better understating of the species. Basic Understanding of project Through initial understanding and contribution to DeepForest, I have grasped a basic understanding that DeepForest uses Retinanet as a one-stage object detection model that utilizes a focal loss function to address class imbalance during training and which is composed of a backbone network. Backbone Network The backbone is responsible for computing a convolutional feature map over an entire input image and is an off-the-self convolutional network to predict individual tree crowns and birds from airborne RGB images. The pre-built model uses a semi

Start of the Coding Period

Start of the Coding Period After the admission to the GSoC program, there is a time period to get started with the project, contact the mentors and so on. After this, the Coding Period starts. This year, it started on May 27th. In my case, I had already contributed to DeepForest, so I had already set up my working environment even before the proposal submission. Thus, I dedicated this period to add detail to my proposal and to discuss with my mentors who were actually very helpful and were always ready to guide and discussed how to tackle the different tasks. I started by checking some papers on multi class object detection and how Resnet works, similar projects and going issue by issue in DeepForest to find all feature requests related to my project. Afterwards I outlined a list of all the methods with their priority and workflow for the whole project which was then discussed with my mentors. I immediately started with a pull request on making the model able to interact with multiple