Flutter 插件使用必知必會

本文目的

  • 介紹插件的搜索方式,三方庫評估的意義和基本思路
  • 介紹如何給應用添加插件,從源碼角度看插件是如何註冊生效的
  • 介紹如何給插件指定版本和解決版本衝突問題
  • 介紹依賴源的種類,如何從pub/git/本地指定依賴庫
  • 介紹依賴的2種分類方式:直接依賴和傳遞依賴;常規依賴和dev依賴
  • 介紹pub這個包管理工具獲取依賴的流程和 lockfile 文件的意義

目錄結構

  • 獲取插件
  • 插件的使用
  • 依賴的分類
  • 包管理
  • 總結

獲取插件

這裏的 Flutter 插件,不是 IDE 中的插件,而指的是包含平臺特定代碼的包,用以提供 Flutter 框架所不支持的一些 Native API 的功能。好比經常使用的 shared_preferences , path_provider 等。java

Flutter 框架爲咱們提供了不少 UI 層的控制和支持,但 APP 的功能並不侷限在顯示上,還須要依賴 Native 平臺的支持,好比文件系統,攝像頭等硬件調用等。因此Flutter爲咱們提供了一個Platform Channel的機制,使得 Dart 代碼能夠與 Navtive 代碼進行交互。基於Platform Channel,開發者能夠編寫本身須要的 Native 功能,在 Dart 代碼中統一調用。android

搜索途徑

隨着Flutter社區的成長和壯大,Flutter Plugin 的數量和質量也在不斷提升。當你在開發本身的 App 時,若是遇到依賴 Native 的功能時,不妨先考慮去社區搜索是否有現成的輪子。推薦2個平臺:ios

pub.dartlang

針對 dart 語言的三方庫平臺,能夠選擇 Flutter 類型進行搜索,更有針對性,每一個庫根據 Popularity ,Health, Maintenance 進行打分,是搜索的首選。首頁還列出了十幾個 Top Popular 的項目,好比 shared_preferences, url_launcher, path_provider,能夠說是基礎必備插件。git

github

flutter plugin 爲關鍵字搜索。相對 pub.dartlang,缺乏針對性和評分體系(能夠根據 issuestar 數進行評估,但相對來講沒有那麼直觀),但庫數量更多,更新更快(好比修復了 bug 不須要等它發佈到 pub 上)。github

不一樣平臺的插件,依賴的寫法也有不一樣,下文會說明。shell

引入前評估

搜索到本身所需功能的插件後,咱們就直接拿來主義嗎?對待開源三方庫,個人傾向是先作多方對比,嘗試閱讀源碼,作到心中有數後再引入。在咱們團隊,若是須要引入三方庫,都必須提供一個說明文檔,進行引入緣由說明。swift

考量要點:緩存

  • 根據 pub score 或者 github 的 issue,star,維護狀況進行評估
  • 功能是否知足需求,API易用性如何
  • 引入後對包大小影響對比
  • 若是庫比較簡單,能夠閱讀源碼,看它的實現方式是否科學規範
  • 看 native 功能是用什麼語言實現,是否 match 團隊的技術棧,好比我司就更偏好 Kotlin/Swift

若是你發現這個庫部分知足了業務需求,你能夠選擇改進它,或者從新造輪子。若是你以爲庫維護者比較勤快和靠譜,項目的底子也不錯,能夠嘗試 Fork 這個項目,並給它提 PRbash

對編寫插件感興趣的童鞋能夠看看這個姊妹篇:Flutter插件編寫必知必會服務器

插件的使用

添加依賴

  1. 打開項目下的pubspec.yaml文件,在 dependencies 下添加依賴名稱和版本等信息

  2. 在命令行下運行flutter packages get,或者在 IDE 中 點擊 Packages Get 等待它下載完成,並生成插件註冊代碼

    • Android:

      • android/app/scr/main/java/io/flutter/plugins目錄下自動生成的GeneratedPluginRegistrant.java中,會添加插件的註冊代碼。
      public final class GeneratedPluginRegistrant {
          public static void registerWith(PluginRegistry registry) {
              if (alreadyRegisteredWith(registry)) { return; }
              UrlLauncherPlugin.registerWith(registry.registrarFor("io.flutter.plugins.urllauncher.UrlLauncherPlugin"));
              ...
          }
          ...
      }
      複製代碼
      • 在 App 的 MainActivity 建立時會去調用這個註冊方法
      class MainActivity : FlutterActivity() {
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              GeneratedPluginRegistrant.registerWith(this)
          }
      }
      複製代碼
    • iOS

      • ios/Runner目錄下自動生成的GeneratedPluginRegistrant.m中,會添加插件的註冊代碼。
      #import "GeneratedPluginRegistrant.h"
      #import <url_launcher/UrlLauncherPlugin.h>
      
      @implementation GeneratedPluginRegistrant
      
      + (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
      [FLTUrlLauncherPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTUrlLauncherPlugin"]];
      }
      
      @end
      複製代碼
      • AppDelegate.swift啓動後去調用註冊
      @UIApplicationMain
      @objc class AppDelegate: FlutterAppDelegate, WXApiDelegate {
      
          override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? ) -> Bool {
              GeneratedPluginRegistrant.register(with: self)
              return super.application(application, didFinishLaunchingWithOptions: launchOptions)
          }
      }
      複製代碼
  3. 在項目文件中 import 所需的包名,並使用

  4. 若是依賴中存在 platform-specific code (Java/Kotlin for Android, Swift/Objective-C for iOS),要確保代碼可以編譯進 App ,必須 Restart App,防止發生MissingPluginException異常。Hot reload 或者 Hot restart 只對 dart 代碼有效。

版本約束

版本格式:主版本號.次版本號.修訂號,版本號遞增規則以下:

  • 主版本號:當你作了不兼容的 API 修改,
  • 次版本號:當你作了向下兼容的功能性新增,
  • 修訂號:當你作了向下兼容的問題修正。

更詳細的參考語義化版本

基本用法:

any # 全部版本,等同於不寫。對pub運行性能有影響,不推薦
1.2.3 # 明確的版本號
'>=1.2.3' # 還有 >1.2.3, <=1.2.3, <1.2.3
^1.2.3 # Caret syntax 等同於 >=1.2.3 <2.0.0
複製代碼

注意:若是在版本約束中使用了'>','<'字符,必定要加引號,不然沒法被看成 YAML 的語法解析

版本衝突

若是項目依賴了 A , B 庫,他們都依賴了一個 C ,但 C 的版本不一樣,可能會產生版本衝突。pub 會嘗試找到符合全部依賴約束的版本號。若是找不到能匹配的版本,但 AB 庫依賴 C 庫的 API 是同樣的,那麼能夠添加一個依賴覆蓋來強制指定某一版本。

注:pub 是 Dart SDK 提供的一個包管理工具

dependencies:
 some_package:
 other_package:
dependency_overrides:
 url_launcher: '0.4.3'
複製代碼

若是是 Android 平臺的庫依賴衝突,能夠在 appgradle 文件中強制指定版本

configurations.all {
    resolutionStrategy {
        force 'com.google.guava:guava:23.0-android'
    }
}
複製代碼

注意: iOS 平臺下 CocoaPods 不支持強制版本覆蓋

從不一樣的依賴源添加依賴

SDK

The SDK source is used for any SDKs that are shipped along with packages, which may themselves be dependencies. Currently, Flutter is the only SDK that is supported.

通俗講,就是 Flutter SDK 自帶的庫。打開咱們 Flutter 的安裝地址,進入flutter/packages能夠看到各類包,如flutter,flutter_driver,flutter_test等。

➜  packages git:(stable) ✗ ls
analysis_options.yaml         flutter_localizations
flutter                       flutter_test
flutter_driver                flutter_tools
flutter_goldens               fuchsia_remote_debug_protocol
flutter_goldens_client
➜  packages git:(stable) ✗ pwd
/Users/xxx/flutter/packages
複製代碼

在 Flutter 項目中寫過測試的同窗對上面幾個依賴應該不陌生

dependencies:
 flutter:
 sdk: flutter # 來源於flutter sdk
dev_dependencies:
 flutter_test:
 sdk: flutter
 flutter_driver:
 sdk: flutter
複製代碼

Hosted

A hosted package is one that can be downloaded from pub.dartlang.org (or another HTTP server that speaks the same API).

pub

dependencies:
 transmogrify: ^1.4.0 
複製代碼

本身的服務器

dependencies:
 transmogrify: ^1.4.0 
 transmogrify:
 hosted:
 name: transmogrify
 url: http://your-package-server.com
 version: ^1.4.0
複製代碼

Git

dependencies:
 kittens:
 git: git://github.com/munificent/kittens.git
複製代碼

指定分支

dependencies:
 kittens:
 url: git://github.com/munificent/kittens.git
 ref: some-branch
複製代碼

pub 默認包目錄在 git 倉庫的根目錄,若是要指定在別的位置,能夠用 path 參數

dependencies:
 kittens:
 git:
 url: git://github.com/munificent/cats.git
 path: path/to/kittens
複製代碼

本地路徑

特別適用在一我的同時開發項目和依賴庫的狀況。由於修改依賴庫的代碼,在項目中就能夠即時生效,有利於調試和提升效率。

dependencies:
 transmogrify:
 path: /Users/me/transmogrify # 也能夠相對路徑,相對路徑以 pubspec.yml 文件爲基準
複製代碼

依賴的分類

直接依賴和傳遞依賴

根據依賴與項目的關係,能夠分爲如下2類:

  • immediate dependency :項目中直接使用的依賴,即咱們在 pubspec 中列出的依賴,包括 dependciesdev_dependencies
  • transitive dependency :直接依賴所需的依賴, pub 會根據 pubspec 中列出的依賴自動爲咱們獲取。

舉個例子

好比咱們項目依賴 A ,而 A 又依賴 BB 又依賴 C 。那麼 A 是咱們項目的immediate dependency, BC 就是transitive dependency

咱們能夠在命令行中輸入命令flutter packages pub deps,查看項目的依賴樹。 好比咱們在項目中引入了一個支持網絡緩存的圖片庫cached_network_image: ^0.5.0+1

flutter packages pub deps
Dart SDK 2.1.0-dev.9.4.flutter-f9ebf21297
Flutter SDK 1.0.1-pre.2
your_app_name 2.2.0+10 # 項目名稱和版本
|-- cached_network_image 0.5.1 # 直接依賴
|   |-- flutter... # 直接依賴(由於在項目pubspec中也添加了)
|   '-- flutter_cache_manager 0.2.0+1 # 傳遞依賴
|       |-- flutter...
|       |-- http...
|       |-- path_provider...
|       |-- shared_preferences...
|       |-- synchronized 1.5.3
|       '-- uuid 1.0.3
|           |-- convert...
|           '-- crypto...
...
複製代碼

常規依賴和dev依賴

根據依賴的做用範圍,能夠分爲:

  • dependencies :常規依賴
  • dev dependencies :開發時所需依賴。它和常規依賴的區別是,項目依賴庫中的 dev dependencies ,對於你的項目來講是不可見的。

舉個例子

項目的 pubspec.yml 以下。若是 A 有一個 dev_dependencies 依賴 dev_C ,項目最終的依賴是 A , dev_B;不包括 dev_C

dependencies:
 A:
dev_dependencies:
 dev_B: 
複製代碼

適應場景:若是你須要 importlib 或者 bin 目錄,那麼選擇 dependencies ; 若是你只須要 importtestexample 等,那麼就選擇 dev dependencies 。使用 dev dependencies 的好處是能讓依賴樹更小,從而使 pub 運行更快,能跟容易找到知足全部約束的包版本。

包管理

在獲取一個新的依賴時,pub 會下載知足版本條件的最新版本,而後把版本信息添加到一個 lockfile 中。這個 lockfile 文件叫 pubspec.lock ,位於項目 pubspec.yml 的同級目錄。它列出了項目的每一個依賴(包括直接依賴和傳遞依賴)的版本信息。咱們應該把這個 lockfile 添加到版本控制中,這樣不論開發環境,生產環境都能確保使用了相同的依賴版本。

舉個例子

項目的 pubspec.yml 文件包含以下依賴

...
dependencies:
 flutter:
 sdk: flutter
 cached_network_image: ^0.5.0+1

dev_dependencies:
 flutter_test:
 sdk: flutter
...
複製代碼

結合上面提到知識,咱們來看看 pubspec.lock 的內容。 lockfile 把全部依賴樹打平,並根據首字母排序

cached_network_image:
    dependency: "direct main" # 直接依賴,常規依賴
    description:
      name: cached_network_image
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "0.5.1"
flutter: 
    dependency: "direct main" # 直接依賴,常規依賴
    description: flutter
    source: sdk
    version: "0.0.0"
flutter_test:
    dependency: "direct dev" # 直接依賴,開發依賴
    description: flutter
    source: sdk
    version: "0.0.0"
uuid:
    dependency: transitive # 傳遞依賴
    description:
      name: uuid
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "1.0.3"
...
複製代碼

若是非首次獲取依賴,pub 會從 lockfile 中讀取版本。若是想升級到知足 pubspec.yml 中約束的最新版本,能夠執行 flutter packages upgrade 命令,升級後會更新 lockfile 中的版本。

總結

本文咱們主要討論了插件的獲取和選擇,同時分析了插件是如何使用並生效的。在介紹插件版本的部分,提到了語義化版本的概念,不論對插件的使用者仍是開發者,都很是有用,推薦你們去細緻的看看。對於依賴的管理, Dart 語言提供了 pub 這個工具,並運用了 lockfile 思想去保證依賴的一致性,也值得你們學習。Flutter在不斷成長,它的生態也在創建,這離不開開源社區的努力,當你發現想要的功能沒有現成的開源庫,不妨本身去寫一寫。

下一篇,咱們來說講Flutter插件編寫必知必會

參考

本文版權屬於再惠研發團隊,歡迎轉載,轉載請保留出處。@akindone

相關文章
相關標籤/搜索