Flutter Package vs Plugin: Understanding the Differences and Uses

Michael PiperMichael Piper
3 min read

In Flutter, both packages and plugins are essential for extending the functionality of your applications. However, they serve different purposes and are used in distinct scenarios. This guide will help you understand the differences between packages and plugins, how to create them, and when to use each.

What is a Flutter Package?

A Flutter package is a reusable set of Dart code that can be used to add functionality to your Flutter application. Packages typically contain Dart libraries, assets, and other resources. They do not include platform-specific code.

Common Uses of Packages

  • Implementing common functionalities like HTTP requests, JSON parsing, or state management.

  • Sharing reusable widgets, services, or utilities.

  • http: For making HTTP requests.

  • provider: For state management.

  • intl: For internationalization and localization.

What is a Flutter Plugin?

A Flutter plugin is a special type of package that includes platform-specific code. Plugins are used to access platform-specific features and APIs that are not available in Dart. They contain both Dart code and platform-specific code (Java/Kotlin for Android, Swift/Objective-C for iOS).

Common Uses of Plugins

  • Accessing device hardware features like camera, GPS, or sensors.

  • Integrating with platform-specific APIs like in-app purchases, push notifications, or file system access.

  • camera: For accessing the device camera.

  • shared_preferences: For persistent storage.

  • path_provider: For accessing commonly used locations on the filesystem.

Key Differences Between Packages and Plugins

FeaturePackagePlugin
CodeDartDart + Platform-specific (Java/Kotlin, Swift/Objective-C)
Platform APIsNoYes
UsageCommon functionalities, reusable codeAccessing platform-specific features and APIs
ComplexityGenerally simplerMore complex due to platform-specific code

Creating a Flutter Package

  1. Create the Package:

     shCopy codeflutter create --template=package my_package
    
  2. Implement the Package:

    • Add Dart code and assets in the lib directory.

    • Example:

        dartCopy codelibrary my_package;
      
        class MyPackage {
          String greet(String name) {
            return 'Hello, $name!';
          }
        }
      
  3. Publishing the Package:

    • Update pubspec.yaml with package details.

    • Publish to pub.dev using:

        shCopy codeflutter pub publish
      

Creating a Flutter Plugin

  1. Create the Plugin:

     shCopy codeflutter create --template=plugin my_plugin
    
  2. Implement the Plugin:

    • Add Dart code in the lib directory.

    • Add platform-specific code in android and ios directories.

    • Example:

        dartCopy code// lib/my_plugin.dart
        import 'dart:async';
        import 'package:flutter/services.dart';
      
        class MyPlugin {
          static const MethodChannel _channel = MethodChannel('my_plugin');
      
          static Future<String> get platformVersion async {
            final String version = await _channel.invokeMethod('getPlatformVersion');
            return version;
          }
        }
      
        javaCopy code// android/src/main/java/com/example/my_plugin/MyPlugin.java
        package com.example.my_plugin;
      
        import androidx.annotation.NonNull;
      
        import io.flutter.embedding.engine.plugins.FlutterPlugin;
        import io.flutter.plugin.common.MethodCall;
        import io.flutter.plugin.common.MethodChannel;
        import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
        import io.flutter.plugin.common.MethodChannel.Result;
      
        public class MyPlugin implements FlutterPlugin, MethodCallHandler {
          private MethodChannel channel;
      
          @Override
          public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
            channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "my_plugin");
            channel.setMethodCallHandler(this);
          }
      
          @Override
          public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
            if (call.method.equals("getPlatformVersion")) {
              result.success("Android " + android.os.Build.VERSION.RELEASE);
            } else {
              result.notImplemented();
            }
          }
      
          @Override
          public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
            channel.setMethodCallHandler(null);
          }
        }
      
  3. Publishing the Plugin:

    • Update pubspec.yaml with plugin details.

    • Publish to pub.dev using:

        shCopy codeflutter pub publish
      

When to Use Packages vs. Plugins

  • Use Packages:

    • When you need reusable Dart code that doesn't require platform-specific APIs.

    • For common functionalities, utilities, and services.

  • Use Plugins:

    • When you need to access platform-specific features or APIs.

    • For integrating device hardware, platform services, or native APIs.

Conclusion

Understanding the differences between Flutter packages and plugins is crucial for effective Flutter development. Packages are ideal for sharing reusable Dart code, while plugins enable you to access platform-specific features. By leveraging both packages and plugins, you can create powerful and versatile Flutter applications that run seamlessly across multiple platforms.

0
Subscribe to my newsletter

Read articles from Michael Piper directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Michael Piper
Michael Piper

Experienced Software Engineer skilled in creating mobile apps and web solutions. Expertise in iOS/Android app development, JavaScript frameworks, Python, and research methodologies. Detail-oriented problem solver with 10+ years of experience delivering top-notch solutions.