An SDK (Software Development Kit) is a set of tools a third-party developer can use in developing their application using a certain framework or platform. In the case of Flutter an SDK would be a single package or a collection of packages that provide certain functionality eg a service to a Flutter application.
An API (Application Programming Interface) is a set for protocols/rules that define how different applications communicate and share data, whilst an SDK is a tool kit to build applications and features.
Lets begin by understanding what a Flutter package is, a Flutter package is a pre-built collection of code that adds functionality and features to your Flutter app. The act as building blocks that are reusable and modular, allowing developers to reuse existing code instead of building everything from scratch. These packages could be widgets, icons, utilities, assets and more.
Flutter packages are added to a Flutter application through the pubspec.yaml
file through the dependancies section:
dependencies:
flutter:
sdk: flutter
ming_cute:
path: packages/ming_cute
cupertino_icons: ^1.0.2
go_router: ^13.0.1
provider: ^6.1.1
graphql_flutter: ^5.2.0-beta.6
json_annotation: ^4.8.1
flutter_svg: ^2.0.10+1
For the keen eyed, you must have noticed that we have flutter
as an SDK listed in the dependencies. Yes, Flutter is an SDK as it provides different tools and utilities to build and compile a Flutter application.
flutter create --template=package my_package
This is a Flutter CLI command that creates a new Flutter-compatible Dart package.
In Flutter applications the main.dart
file holds the main entry point for the application through the main()
function. All app execution begins from this function. Since packages don’t require executing independently whenever the application starts. They don’t hold a main()
entry point. Packages however, contain their own central file with the same name as the package. eg if your package is named ming_cute_icons
then the file is called ming_cute_icons.dart
.
So then, whats the point of this file ?
A package contains several classes and files to achieve the functionality that it is meant to perform. However, not all of these classes and methods need to be exposed. Some things may even need to be specifically hidden. The main purpose of the central file is to define what files from the package are exposed to the app. The file may also expose other packages that it imports.
Let’s assume this is our package structure for a hypothetical calculator package: simple_calc
lib/
├─ simple_calc.dart
├─ src/
│ ├─ calculator.dart
│ ├─ utils/
│ │ ├─ math_utils.dart
│ ├─ models/
│ │ ├─ number_model.dart
In this structure, simple_calc.dart
file is our central file. We may want to expose the calculator class and the number_model.dart
, but not the math_utils.dart
. We use the export
keyword for exposing files to the app.
For this, the simple_calc.dart
file will look like this:
export 'calculator.dart';
export 'models/number_model.dart';
You do not need to specifically hide anything if you do not want to expose it. All files not exported are hidden by default. You can use the show
and hide
keywords to only show certain things or hide certain things respectively. For example, let’s say we only want to show the calculator class from the calculator.dart
file and hide an ImaginaryNumber
class from the number_model.dart
.
This is how we would write the mentioned scenario:
export 'calculator.dart' show Calculator;
export 'models/number_model.dart' hide ImaginaryNumber;
Something to note is that the general convention when creating packages is to add a src
folder inside the lib
folder that includes everything except the central file. This allows separation between the central file and the package’s source code.
In general, the pubspec.yaml
file in an app is a combination of metadata about a project and the dependencies it imports. The pubspec.yaml
belonging to a package is similar to one that belongs to an app but contains different metadata compared to an app and certain added restrictions for dependencies.
Since the file is a YAML file, it contains various properties about the package. Let’s review some of the possible properties you can set in the file. This may not be an exhaustive list; however, these are some of the main properties used when creating a package.
name: simple_calc
description: A simple calculator package for Flutter and Dart.
version: 1.0.0
homepage: https://github.com/yourusername/simple_calc
repository: https://github.com/yourusername/simple_calc
issue_tracker: https://github.com/yourusername/simple_calc/issues
documentation: https://github.com/yourusername/simple_calc/wiki
publish_to: https://pub.dev
environment:
sdk: ">=3.0.0 <4.0.0"
flutter: ">=3.10.0"
dependencies:
flutter:
sdk: flutter
# Add any other package dependencies here
math_expressions: ^2.2.0
dev_dependencies:
flutter_test:
sdk: flutter
lints: ^3.0.0
issue_tracker
field should feature a URL directing to the package’s issue tracker, helping users view existing bugs and file new ones. In cases where issue_tracker
is absent but the repository is present and directs to GitHub, the pub.dev site defaults to using the issue tracker at the repository issues page.publish_to
to publish your packages to another custom server or stop publishing anything altogether.When you finish implementing the functionality within your Flutter package, it’s time to publish.
Before you publish, here are a few steps we (and pub) recommend following:
dart format
).pana
command to check and analyse anything wrong with your package.CHANGELOG.md
and pubspec.yaml
are updated with the newest changes.To publish a Flutter package, you can simply run the following command in your package:
flutter pub publish
However, before you do, its recommended doing a dry run for your publish by adding the same flag:
flutter pub publish --dry-run
After this you will get to see your package on Google’s pub.dev such as these:
Note that you can use a package without publishing it to pub.dev - this is done through importing a package from GitHub like so:
dependencies:
packageA:
git:
url: https://github.com/flutter/packageA.git
Creating a Flutter package is a great way to increase the adoption of your service by making integration simple and seamless for other developers. Whether you’re working as an individual developer or part of a team, packaging your code can save others from facing the same challenges you’ve already solved. By sharing your solution, you contribute to the wider developer community and help accelerate app development. I’ll be documenting the full process of building and publishing a Flutter package soon, and I’m also considering open-sourcing the project to encourage collaboration and feedback.