- Install
- Set up an editor
- Test drive
- Write your first Flutter app, part 1
- Learn more
- Flutter for Android developers
- Flutter for iOS developers
- Flutter for React Native developers
- Flutter for web developers
- Flutter for Xamarin.Forms developers
- Introduction to declarative UI
- Cookbook
- Codelabs
- Tutorials
- User interface
- Introduction to widgets
- Layouts in Flutter
- Layout tutorial
- Dealing with box constraints
- Adding interactivity to your Flutter app
- Adding assets and images
- Navigation & routing
- Introduction to animations
- Animations overview
- Animations tutorial
- Hero Animations
- Staggered Animations
- Advanced UI
- Slivers
- Taps, drags, and other gestures
- Widget catalog
- Data & backend
- State management
- State management
- Start thinking declaratively
- Differentiate between ephemeral state and app state
- Simple app state management
- List of state management approaches
- JSON and serialization
- Firebase
- Accessibility & internationalization
- Accessibility
- Internationalizing Flutter apps
- Platform integration
- Writing custom platform-specific code
- Packages & plugins
- Using packages
- Developing packages & plugins
- Background processes
- Tools & techniques
- Android Studio / IntelliJ
- Visual Studio Code
- Upgrading Flutter
- Hot reload
- Code formatting
- Debugging Flutter apps
- Using OEM debuggers
- Flutter's build modes
- Testing Flutter apps
- Performance best practices
- Flutter performance profiling
- Creating flavors for Flutter
- Preparing an Android App for Release
- Preparing an iOS App for Release
- Continuous Delivery using fastlane with Flutter
- Bootstrap into Dart
- Inside Flutter
- Platform specific behaviors and adaptations
- Technical Overview
- Technical videos
- FAQ
- Flutter widget index
- Install
- Windows install
- MacOS install
- Linux install
- Set up an editor
- Write your first Flutter app, part 1
- Learn more
- Cupertino (iOS-style) widgets
- Layout widgets
- Animation and motion widgets
- Retrieve the value of a text field
- Basic widgets
- Material Components widgets
- Animate the properties of a Container
- Fade a Widget in and out
- Add a Drawer to a screen
- Displaying SnackBars
- Exporting fonts from a package
- Updating the UI based on orientation
- Using Themes to share colors and font styles
- Using custom fonts
- Working with Tabs
- Building a form with validation
- Create and style a text field
- Focus on a Text Field
- Handling changes to a text field
- Retrieve the value of a text field
- Adding Material Touch Ripples
- Handling Taps
- Implement Swipe to Dismiss
- Display images from the internet
- Fade in images with a placeholder
- Working with cached images
- Basic List
- Create a horizontal list
- Creating a Grid List
- Creating lists with different types of items
- Place a floating app bar above a list
- Working with long lists
- Report errors to a service
- Animating a Widget across screens
- Navigate to a new screen and back
- Navigate with named routes
- Pass arguments to a named route
- Return data from a screen
- Send data to a new screen
- Fetch data from the internet
- Making authenticated requests
- Parsing JSON in the background
- Working with WebSockets
- Persist data with SQLite
- Reading and Writing Files
- Storing key-value data on disk
- Play and pause a video
- Take a picture using the Camera
- An introduction to integration testing
- Performance profiling
- Scrolling
- An introduction to unit testing
- Mock dependencies using Mockito
- An introduction to widget testing
- Finding widgets
- Tapping, dragging and entering text
- Development
- Introduction to widgets
- Layout tutorial
- Dealing with box constraints
- Adding interactivity to your Flutter app
- Adding assets and images
- Navigation & routing
- Navigate to a new screen and back
- Send data to a new screen
- Return data from a screen
- Navigate with named routes
- Animating a Widget across screens
- AnimatedList
- Sample App Catalog
- Animations overview
- Animations tutorial
- Staggered Animations
- Slivers
- Taps, drags, and other gestures
- Accessibility widgets
- Assets, images, and icon widgets
- Async widgets
- Input widgets
- Interaction model widgets
- Painting and effect widgets
- Scrolling widgets
- Styling widgets
- Text widgets
- State management
- Start thinking declaratively
- Differentiate between ephemeral state and app state
- Simple app state management
- List of state management approaches
- JSON and serialization
- Accessibility
- Internationalizing Flutter apps
- Writing custom platform-specific code
- Using packages
- Fetch data from the internet
- Developing packages & plugins
- Background processes
- Android Studio / IntelliJ
- Set up an editor
- Flutter inspector
- Creating Useful Bug Reports
- Visual Studio Code
- Set up an editor
- Upgrading Flutter
- Hot reload
- Code formatting
Developing packages & plugins
Package introduction
Packages enable the creation of modular code that can be shared easily. A minimal package consists of:
A
pubspec.yaml
file: A metadata file that declares the package name, version, author, etc.A
lib
directory containing the public code in the package, minimally a single<package-name>.dart
file.
Package types
Packages can contain several kinds of content:
Dart packages: General packages written in Dart, for example the
path
package. Some of these may contain Flutter specific functionality and thus have a dependency on the Flutter framework, restricting their use to Flutter only, for example thefluro
package.Plugin packages: A specialized Dart package which contain an API written in Dart code combined with a platform-specific implementation for Android (using Java or Kotlin), and/or for iOS (using ObjC or Swift). A concrete example is the
battery
plugin package.
Developing Dart packages
Step 1: Create the package
To create a Dart package, use the --template=package
flag with flutter create
:
$ flutter create --template=package hello
This creates a package project in the hello/
folder with the following specialized content:
lib/hello.dart
:- The Dart code for the package.
test/hello_test.dart
:- The unit tests for the package.
Step 2: Implement the package
For pure Dart packages, simply add the functionality inside the main lib/<package name>.dart
file, or in several files in the lib
directory.
To test the package, add unit tests in a test
directory.
For additional details on how to organize the package contents, see the Dart library package documentation.
Developing plugin packages
If you want to develop a package that calls into platform-specific APIs, you need to develop a plugin package. A plugin package is a specialized version of a Dart package, that in addition to the content described above also contains platform-specific implementations written for Android (Java or Kotlin code), for iOS (Objective-C or Swift code), or for both. The API is connected to the platform-specific implementation(s) using platform channels.
Step 1: Create the package
To create a plugin package, use the --template=plugin
flag with flutter create
.
Use the --org
option to specify your organization, using reverse domain name notation. This value is used in various package and bundle identifiers in the generated Android and iOS code.
$ flutter create --org com.example --template=plugin hello
This creates a plugin project in the hello/
folder with the following specialized content:
lib/hello.dart
:- The Dart API for the plugin.
android/src/main/java/com/example/hello/HelloPlugin.java
:- The Android platform specific implementation of the plugin API.
ios/Classes/HelloPlugin.m
:- The iOS platform specific implementation of the plugin API.
example/
:- A Flutter app that depends on the plugin, and illustrates how to use it.
By default, the plugin project uses Objective-C for iOS code and Java for Android code. If you prefer Swift or Kotlin, you can specify the iOS language using -i
and/or the Android language using -a
. For example:
$ flutter create --template=plugin -i swift -a kotlin hello
Step 2: Implement the package
As a plugin package contains code for several platforms written in several programming languages, some specific steps are needed to ensure a smooth experience.
Step 2a: Define the package API (.dart)
The API of the plugin package is defined in Dart code. Open the main hello/
folder in your favorite Flutter editor. Locate the file lib/hello.dart
.
Step 2b: Add Android platform code (.java/.kt)
We recommend you edit the Android code using Android Studio.
Before editing the Android platform code in Android Studio, first make sure that the code has been built at least once (i.e., run the example app from your IDE/editor, or in a terminal execute cd hello/example; flutter build apk
).
Next,
- Launch Android Studio
- Select ‘Import project’ in ‘Welcome to Android Studio’ dialog, or select ‘File > New > Import Project…’’ in the menu, and select the
hello/example/android/build.gradle
file. - In the ‘Gradle Sync’ dialog, select ‘OK’.
- In the ‘Android Gradle Plugin Update’ dialog, select ‘Don’t remind me again for this project’.
The Android platform code of your plugin is located in hello/java/com.example.hello/HelloPlugin
.
You can run the example app from Android Studio by pressing the ▶ button.
Step 2c: Add iOS platform code (.h+.m/.swift)
We recommend you edit the iOS code using Xcode.
Before editing the iOS platform code in Xcode, first make sure that the code has been built at least once (i.e., run the example app from your IDE/editor, or in a terminal execute cd hello/example; flutter build ios --no-codesign
).
Next,
- Launch Xcode
- Select ‘File > Open’, and select the
hello/example/ios/Runner.xcworkspace
file.
The iOS platform code of your plugin is located in Pods/Development Pods/hello/Classes/
in the Project Navigator.
You can run the example app by pressing the ▶ button.
Step 2d: Connect the API and the platform code
Finally, you need to connect the API written in Dart code with the platform-specific implementations. This is done using platform channels.
Adding documentation
It is recommended practice to add the following documentation to all packages:
- A
README.md
file that introduces the package - A
CHANGELOG.md
file that documents changes in each version - A
LICENSE
file containing the terms under which the package is licensed - API documentation for all public APIs (see below for details)
API documentation
When you publish a package, API documentation is automatically generated and published to dartdocs.org, see for example the device_info docs
If you wish to generate API documentation locally on your developement machine, use the following commands:
Change directory to the location of your package:
cd ~/dev/mypackage
Tell the documentation tool where the Flutter SDK is (change to reflect where you placed it):
export FLUTTER_ROOT=~/dev/flutter
(on macOS or Linux)set FLUTTER_ROOT=~/dev/flutter
(on Windows)Run the
dartdoc
tool (comes as part of the Flutter SDK):$FLUTTER_ROOT/bin/cache/dart-sdk/bin/dartdoc
(on macOS or Linux)%FLUTTER_ROOT%\bin\cache\dart-sdk\bin\dartdoc
(on Windows)
For tips on how to write API documentation, see Effective Dart: Documentation.
Publishing packages
Once you have implemented a package, you can publish it on the Pub site, so that other developers can easily use it.
Prior to publishing, make sure to review the pubspec.yaml
, README.md
, and CHANGELOG.md
files to make sure their content is complete and correct.
Next, run the dry-run command to see if everything passes analysis:
$ flutter packages pub publish --dry-run
Finally, run the actual publish command:
$ flutter packages pub publish
For details on publishing, see the publishing docs. for the Pub site.
Handling package interdependencies
If you are developing a package hello
that depends on the Dart API exposed by another package, you need to add that package to the dependencies
section of your pubspec.yaml
file. The code below makes the Dart API of the url_launcher
plugin available to hello
:
In hello/pubspec.yaml
:
dependencies:
url_launcher: ^0.4.2
You can now import 'package:url_launcher/url_launcher.dart'
and launch(someUrl)
in the Dart code of hello
.
This is no different from how you include packages in Flutter apps or any other Dart project.
But if hello
happens to be a plugin package whose platform-specific code needs access to the platform-specific APIs exposed by url_launcher
, you also need to add suitable dependency declarations to your platform-specific build files, as shown below.
Android
In hello/android/build.gradle
:
android {
// lines skipped
dependencies {
provided rootProject.findProject(":url_launcher")
}
}
You can now import io.flutter.plugins.urllauncher.UrlLauncherPlugin
and access the UrlLauncherPlugin
class in the source code at hello/android/src
.
iOS
In hello/ios/hello.podspec
:
Pod::Spec.new do |s|
# lines skipped
s.dependency 'url_launcher'
You can now #import "UrlLauncherPlugin.h"
and access the UrlLauncherPlugin
class in the source code at hello/ios/Classes
.
Conflict resolution
Suppose you want to use some_package
and other_package
in your package hello
, and both of these depend on url_launcher
, but in different versions. Then we have a potential conflict. The best way to avoid this is for package authors to use version ranges rather than specific versions when specifying dependencies.
dependencies:
url_launcher: ^0.4.2 # Good, any 0.4.x with x >= 2 will do.
image_picker: '0.1.1' # Not so good, only 0.1.1 will do.
If some_package
declares the dependencies above and other_package
declares a compatible url_launcher
dependency like '0.4.5'
or ^0.4.0
, pub
is able to resolve the issue automatically. Similar remarks apply to plugin packages’ platform-specific dependencies on Gradle modules and/or CocoaPods.
Even if some_package
and other_package
declare incompatible versions for url_launcher
, it may still be that they actually use url_launcher
in compatible ways. Then the conflict can be dealt with by adding a dependency override declaration to the pubspec.yaml
file in hello
, forcing the use of a particular version.
Forcing the use of url_launcher
version 0.4.3
in hello/pubspec.yaml
:
dependencies:
some_package:
other_package:
dependency_overrides:
url_launcher: '0.4.3'
If the conflicting dependency is not itself a package, but an Android-specific library like guava
, the dependency override declaration must be added to Gradle build logic instead.
Forcing the use of guava
version 23.0
in hello/android/build.gradle
:
configurations.all {
resolutionStrategy {
force 'com.google.guava:guava:23.0-android'
}
}
CocoaPods does not currently offer dependency override functionality.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论