Flutter實戰(zhàn) 開發(fā)Package

2021-03-09 10:13 更新

第二章中已經(jīng)講過如何使用 Package(包),我們知道通過 package 可以創(chuàng)建共享的模塊化代碼,本節(jié)將重點講一下如何開發(fā)并發(fā)布我們自己的 Package。一個最小的 Package 包括:

  • 一個pubspec.yaml文件:聲明了 Package 的名稱、版本、作者等的元數(shù)據(jù)文件。
  • 一個 lib 文件夾:包括包中公開的(public)代碼,最少應有一個<package-name>.dart文件

Flutter Packages 分為兩類:

  • Dart 包:其中一些可能包含 Flutter 的特定功能,因此對 Flutter 框架具有依賴性,這種包僅用于Flutter,例如fluro (opens new window)包。
  • 插件包:一種專用的 Dart 包,其中包含用 Dart 代碼編寫的 PI,以及針對 Android(使用 Java 或 Kotlin)和針對 iOS(使用 OC 或 Swift)平臺的特定實現(xiàn),也就是說插件包括原生代碼,一個具體的例子是battery (opens new window)插件包。

注意,雖然 Flutter 的 Dart 運行時和 Dart VM 運行時不是完全相同,但是如果 Package 中沒有涉及這些存在差異的部分,那么這樣的包可以同時支持 Flutter 和 Dart VM,如 Dart http 網(wǎng)絡庫dio (opens new window)

下面我將帶領讀者一步步來開發(fā)一個 Dart Package。

#第一步:創(chuàng)建Dart包

您可以通過 Android Studio:File>New>New Flutter Project 來創(chuàng)建一個 Package 工程,如圖12-1所示:

圖12-1

您也可以通過使用--template=package 來執(zhí)行 flutter create 命令來創(chuàng)建:

flutter create --template=package hello

這將在hello/文件夾下創(chuàng)建一個具有以下專用內容的 package 工程:

  • lib/hello.dart:Package 的 Dart 代碼
  • test/hello_test.dart:Package 的單元測試代碼。

#實現(xiàn)package

對于純 Dart 包,只需在主lib/<package name>.dart文件內或lib目錄中的文件中添加功能即可 。要測試軟件包,請在test目錄中添加unit tests (opens new window)。下面我們看看如何組織 Package 包的代碼,我們以 shelf Package 為例,它的目錄結構如圖12-2所示:

在 lib 根目錄下的“shelf.dart”中,導出了多個“l(fā)ib/src”目錄下的 dart 文件:

export 'src/cascade.dart';
export 'src/handler.dart';
export 'src/handlers/logger.dart';
export 'src/hijack_exception.dart';
export 'src/middleware.dart';
export 'src/pipeline.dart';
export 'src/request.dart';
export 'src/response.dart';
export 'src/server.dart';
export 'src/server_handler.dart';

而 Package 中主要的功能的源碼都在 src 目錄下。shelf Package 也導出了一個迷你庫: shelf_io,它主要是處理 HttpRequest 的。

#導入包

當需要使用這個 Package 時,我們可以通過"package:"指令來指定包的入口文件:

import 'package:utilities/utilities.dart';

同一個包中的源碼文件之間也可以使用相對路徑來導入。

#生成文檔

可以使用 dartdoc (opens new window)工具來為 Package 生成文檔,開發(fā)者需要做的就是遵守文檔注釋語法在代碼中添加文檔注釋,最后使用 dartdoc 可以直接生成 API 文檔(一個靜態(tài)網(wǎng)站)。文檔注釋是使用三斜線"///"開始,如:

/// The event handler responsible for updating the badge in the UI.
void updateBadge() {
  ...
}

詳細的文檔語法請參考dartdoc (opens new window)。

#處理包的相互依賴

如果我們正在開發(fā)一個hello包,它依賴于另一個包,則需要將該依賴包添加到pubspec.yaml文件的dependencies部分。 下面的代碼使url_launcher插件的 API 在hello包中是可用的:

hello/pubspec.yaml中:

dependencies:
  url_launcher: ^0.4.2

現(xiàn)在可以在helloimport 'package:url_launcher/url_launcher.dart' 然后調用 launch()方法了。

這與在Flutter應用程序或任何其他 Dart 項目中引用軟件包沒有什么不同。

但是,如果hello碰巧是一個插件包,其平臺特定的代碼需要訪問url_launcher公開的特定于平臺的 API,那么我們還需要為特定于平臺的構建文件添加合適的依賴聲明,如下所示。

Android

hello/android/build.gradle:

android {
    // lines skipped
    dependencies {
        provided rootProject.findProject(":url_launcher")
    }
}

您現(xiàn)在可以在hello/android/src源碼中import io.flutter.plugins.urllauncher.UrlLauncherPlugin訪問UrlLauncherPlugin類。

iOS

hello/ios/hello.podspec:

Pod::Spec.new do |s|
  # lines skipped
  s.dependency 'url_launcher'

您現(xiàn)在可以在hello/ios/Classes源碼中 #import "UrlLauncherPlugin.h" 然后訪問 UrlLauncherPlugin類。

#解決依賴沖突

假設我們想在我們的hello包中使用some_packageother_package,并且這兩個包都依賴url_launcher,但是依賴的是url_launcher的不同的版本。 那我們就有潛在的沖突。避免這種情況的最好方法是在指定依賴關系時,程序包作者使用版本范圍 (opens new window)而不是特定版本。

dependencies:
  url_launcher: ^0.4.2    # 這樣會較好, 任何0.4.x(x >= 2)都可.
  image_picker: '0.1.1'   # 不是很好,只有0.1.1版本.

如果some_package聲明了上面的依賴關系,other_package聲明了url_launcher版本像’0.4.5’或’^0.4.0’,pub將能夠自動解決問題。

即使some_packageother_package聲明了不兼容的url_launcher版本,它仍然可能會和url_launcher以兼容的方式正常工作。 你可以通過向hello包的pubspec.yaml文件中添加依賴性覆蓋聲明來處理沖突,從而強制使用特定版本:

強制使用 0.4.3版本的url_launcher,在 hello/pubspec.yaml中:

dependencies:
  some_package:
  other_package:
dependency_overrides:
  url_launcher: '0.4.3'

如果沖突的依賴不是一個包,而是一個特定于 Android 的庫,比如guava,那么必須將依賴重寫聲明添加到 Gradle 構建邏輯中。

強制使用23.0版本的guava庫,在hello/android/build.gradle中:

configurations.all {
    resolutionStrategy {
        force 'com.google.guava:guava:23.0-android'
    }
}

Cocoapods 目前不提供依賴覆蓋功能。

#發(fā)布Package

一旦實現(xiàn)了一個包,我們可以在Pub (opens new window)上發(fā)布它 ,這樣其他開發(fā)者就可以輕松使用它。

在發(fā)布之前,檢查pubspec.yaml、README.md以及CHANGELOG.md文件,以確保其內容的完整性和正確性。然后,運行 dry-run 命令以查看是否都準備OK了:

flutter packages pub publish --dry-run

驗證無誤后,我們就可以運行發(fā)布命令了:

flutter packages pub publish

如果你遇到包發(fā)布失敗的情況,先檢查是否因為眾所周知的網(wǎng)絡原因,如果是網(wǎng)絡問題,可以使用 VPN,這里需要注意的是一些代理只會代理部分 APP 的網(wǎng)絡請求,如瀏覽器的,它們可能并不能代理 dart 的網(wǎng)絡請求,所以在這種情況下,即使開了代理也依然無法連接到 Pub,因此,在發(fā)布 Pub 包時使用全局代理或全局 VPN 會保險些。如果網(wǎng)絡沒有問題,以管理員權限(sudo)運行發(fā)布命令重試。
很多時候開啟全局代理也不會讓 terminal 中的流量打代理服務器走,以 socks5 為例,應該在終端下輸入以下指令:

export all_proxy=socks5://127.0.0.1:1080

此時終端中的 http 和 https 流量會打代理服務器走,可以通過curl -i https://ip.cn指令查看代理設置是否成功。

以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號