Creating and Publishing a Flutter Package

In this tutorial, you’ll learn how to create and publish your own Dart packages to be used in Flutter apps. By Edson Bueno.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

Understanding the library Keyword

Returning to your focus_detector project, open lib/focus_detector.dart that Android Studio generated for you. Look at the first line:

library focus_detector;

This sets the name of the file’s library to focus_detector. The default library name is the filename, making this line unnecessary. So why have a library keyword? There are two cases in which you might want to specify a library name:

  1. Adding library-level documentation to your package. The dartdoc tool requires a library directive to generate library-level documentation. For example:
  2. /// Contains utility functions for displaying dialogs and snackbars.
    library alert_utils;
    
  3. Giving the library a different name.
/// Contains utility functions for displaying dialogs and snackbars.
library alert_utils;

When you import a library, you give the uniform resource identifier (URI) to the import directive, not the library name. So the only place you can actually see the name is in the documentation page. As you see, there’s little point in changing the name.

That said, the Dart documentation recommends you omit the library directive from your code unless you plan to generate library-level documentation.

Enough with the talk! You’re now ready for some action.

Adjusting the Pubspec

Open your new project’s pubspec.yaml file. Notice that the content of the file is grouped into five sections: metadata, environment, dependencies, dev_dependencies, and flutter. For this tutorial, you’ll need only the first three:

Pubspec.yaml contents grouped in blocks

Note: See The pubspec file for more information on supported fields.

Everything users need to find your package comes out of here.

You already provided parts of this information when creating the project. Now you need only a few adjustments:

This should be your result:

Use this section to restrict the Dart or Flutter SDK versions of your users. This is useful if, for example, your package relies on a feature introduced in an earlier Flutter release or you still haven’t complied with a breaking change in the API.

For this tutorial, the defaults are great.

Packages can also depend on other packages. This section is no different than the one you find in your apps. FocusDetector uses the 0.1.5 version of a package published by google.dev called VisibilityDetector. Specify the dependency, then make sure your section looks like this:

  1. The Metadata

    Everything users need to find your package comes out of here.

    You already provided parts of this information when creating the project. Now you need only a few adjustments:

    • version: Replace 0.0.1 with 1.0.0. Unless you’re publishing unfinished or experimental code, avoid 0.*.* version numbers. It might scare off some users.
    • author: This property is no longer used, so delete it.
    • homepage: Put https://github.com/EdsonBueno/focus_detector. The URL doesn’t have to be from a git repository, but that’s the most common usage.
    Note: Remember: The focus_detector package is already published on pub.dev. The homepage field here is being set to the existing code repository.

    This should be your result:

    name: focus_detector
    description: Detects when your widget appears or disappears from the screen.
    version: 1.0.0
    homepage: https://github.com/EdsonBueno/focus_detector
    
  2. The Environment
  3. Use this section to restrict the Dart or Flutter SDK versions of your users. This is useful if, for example, your package relies on a feature introduced in an earlier Flutter release or you still haven’t complied with a breaking change in the API.

    For this tutorial, the defaults are great.

  4. The Dependencies
  5. Packages can also depend on other packages. This section is no different than the one you find in your apps. FocusDetector uses the 0.1.5 version of a package published by google.dev called VisibilityDetector. Specify the dependency, then make sure your section looks like this:

    dependencies:
      flutter:
        sdk: flutter
      visibility_detector: ^0.1.5
    
Note: Remember: The focus_detector package is already published on pub.dev. The homepage field here is being set to the existing code repository.
name: focus_detector
description: Detects when your widget appears or disappears from the screen.
version: 1.0.0
homepage: https://github.com/EdsonBueno/focus_detector
dependencies:
  flutter:
    sdk: flutter
  visibility_detector: ^0.1.5

Last, click Pub get at the top of your screen to download your new dependency.

Now that FocusDetector has a new place to call home, it’s finally time to bring it in.

Bringing the Code

Go back to the yes_we_scan project on Android Studio. Copy lib/utils/focus_detector.dart and paste it under the lib folder of the focus_detector project. When presented with the Copy dialog, click Refactor. Then, on the next dialog, click Overwrite.

Instructions for copying focus_detector.dart from one project to another

By replacing the old lib/focus_detector.dart Android Studio had created for you, you broke the tests. Because testing is outside the scope of this article, delete the test directory as a quick fix.

Note: If you’re interested in testing, check out the Unit Testing With Flutter: Getting Started and Widget Testing With Flutter: Getting Started tutorials.

Analyzing the Code

You can’t build and run a package. What you can do is run the flutter analyze command on your terminal to analyze your code for issues.

Open Android Studio’s shell by clicking Terminal at the bottom of your screen. Then, type in flutter analyze and press Enter, as shown below.

Instructions for running the flutter analyze command

Note: If you prefer to do this outside of Android Studio, with a terminal application of your choice, don’t forget to navigate to the project’s root directory first.

The command should give you a No issues found! message. If that’s the case, you’re good to go.

Structuring Packages

Focus Detector is a single-class package, so there isn’t much thinking to do about how to organize it. But what if your next package contains many files? Some of them you might want exposed to your users, while others you might prefer to keep private. When that is the case, the convention tells you to follow these simple rules:

  1. Keep your implementation files under the lib/src directory. All code inside this folder is private and should never be directly imported by your users.
  2. To make these implementation files public, use the export keyword from a file that is directly under lib, like in the previous alert_utils example above.

The main benefit of this approach is being able to change your internal structure later without affecting end users.

An extension of the second rule is that there should be a library file directly under lib with the same name as your project that exports all your public implementation files. Think of it as your “main” library file. The advantage is that users can explore all your functionalities by importing a single file.

It isn’t an anatomy class if it doesn’t have a dissected body. :] So take a look at the internal structure of a more complex package, the Infinite Scroll Pagination:

File structure of the Infinite Scroll Pagination package

If you want to know more about the Infinite Scroll Pagination package, check out Infinite Scrolling Pagination in Flutter.