2.0 包管理與資源管理
2.0.1 包管理
在軟件開發中,不少時候有一些公共的庫或SDK可能會被不少項目用到,所以,將這些代碼單獨抽到一個獨立模塊,而後哪一個項目須要使用時再直接集成這個模塊,即可大大提升開發效率。不少編程語言或開發工具都支持這種「模塊共享」機制,如Java語言中這種獨立模塊會被打成一個jar包,Android中的aar包,Web開發中的npm包等。爲了方便表述,咱們將這種可共享的獨立模塊統一稱爲「包」( Package)。html
一個APP在實際開發中每每會依賴不少包,而這些包一般都有交叉依賴關係、版本依賴等,若是由開發者手動來管理應用中的依賴包將會很是麻煩。所以,各類開發生態或編程語言官方一般都會提供一些包管理工具,好比在Android提供了Gradle來管理依賴,iOS用Cocoapods或Carthage來管理依賴,Node中經過npm等。而在Flutter開發中也有本身的包管理工具。本節咱們主要介紹一下flutter如何使用配置文件pubspec.yaml
(位於項目根目錄)來管理第三方依賴包。node
YAML是一種直觀、可讀性高而且容易被人類閱讀的文件格式,它和xml或Json相比,它語法簡單並不是常容易解析,因此YAML經常使用於配置文件,Flutter也是用yaml文件做爲其配置文件。Flutter項目默認的配置文件是pubspec.yaml
,咱們看一個簡單的示例:android
name: flutter_in_actiondescription: First Flutter application.
version: 1.0.0+1
dependencies: flutter: sdk: flutter cupertino_icons: ^0.1.2
dev_dependencies: flutter_test: sdk: flutter
flutter: uses-material-design: true
下面,咱們逐一解釋一下各個字段的意義:git
•name
:應用或包名稱。•description
: 應用或包的描述、簡介。•version
:應用或包的版本號。•dependencies
:應用或包依賴的其它包或插件。•dev_dependencies
:開發環境依賴的工具包(而不是flutter應用自己依賴的包)。•flutter
:flutter相關的配置選項。github
若是咱們的Flutter應用自己依賴某個包,咱們須要將所依賴的包添加到dependencies
下,接下來咱們經過一個例子來演示一下如何添加、下載並使用第三方包。shell
Pub倉庫
Pub(https://pub.dev/ )是Google官方的Dart Packages倉庫,相似於node中的npm倉庫,android中的jcenter。咱們能夠在Pub上面查找咱們須要的包和插件,也能夠向Pub發佈咱們的包和插件。咱們將在後面的章節中介紹如何向Pub發佈咱們的包和插件。npm
示例
接下來,咱們實現一個顯示隨機字符串的widget。有一個名爲「english_words」的開源軟件包,其中包含數千個經常使用的英文單詞以及一些實用功能。咱們首先在pub上找到english_words這個包(如圖2-5所示),肯定其最新的版本號和是否支持Flutter。編程
咱們看到「english_words」包最新的版本是3.1.3,而且支持flutter,接下來:json
1.微信
將「english_words」(3.1.3版本)添加到依賴項列表,以下:
dependencies: flutter: sdk: flutter
cupertino_icons: ^0.1.0 # 新添加的依賴 english_words: ^3.1.3
2.
下載包。在Android Studio的編輯器視圖中查看pubspec.yaml時(圖2-6),單擊右上角的 Packages get 。
這會將依賴包安裝到您的項目。咱們能夠在控制檯中看到如下內容:
flutter packages getRunning "flutter packages get" in flutter_in_action...Process finished with exit code 0
咱們也能夠在控制檯,定位到當前工程目錄,而後手動運行flutter packages get
命令來下載依賴包。另外,須要注意dependencies
和dev_dependencies
的區別,前者的依賴包將做爲APP的源碼的一部分參與編譯,生成最終的安裝包。然後者的依賴包只是做爲開發階段的一些工具包,主要是用於幫助咱們提升開發、測試效率,好比flutter的自動化測試包等。
3.
引入english_words
包。
import 'package:english_words/english_words.dart';
在輸入時,Android Studio會自動提供有關庫導入的建議選項。導入後該行代碼將會顯示爲灰色,表示導入的庫還沒有使用。
4.使用english_words
包來生成隨機字符串。
class RandomWordsWidget extends StatelessWidget { @override Widget build(BuildContext context) { // 生成隨機字符串 final wordPair = new WordPair.random(); return Padding( padding: const EdgeInsets.all(8.0), child: new Text(wordPair.toString()), ); }}
咱們將RandomWordsWidget
添加到 _MyHomePageState.build
的Column
的子widget中。
Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ ... //省略無關代碼 RandomWordsWidget(), ],)
若是應用程序正在運行,請使用熱重載按鈕(⚡️圖標) 更新正在運行的應用程序。每次單擊熱重載或保存項目時,都會在正在運行的應用程序中隨機選擇不一樣的單詞對。這是由於單詞對是在 build
方法內部生成的。每次熱更新時,build
方法都會被執行,運行效果如圖2-7所示。
其它依賴方式
上文所述的依賴方式是依賴Pub倉庫的。但咱們還能夠依賴本地包和git倉庫。
•
依賴本地包
若是咱們正在本地開發一個包,包名爲pkg1,咱們能夠經過下面方式依賴:
dependencies: pkg1: path: ../../code/pkg1
路徑能夠是相對的,也能夠是絕對的。
•
依賴Git:你也能夠依賴存儲在Git倉庫中的包。若是軟件包位於倉庫的根目錄中,請使用如下語法
dependencies: pkg1: git: url: git://github.com/xxx/pkg1.git
上面假定包位於Git存儲庫的根目錄中。若是不是這種狀況,可使用path參數指定相對位置,例如:
dependencies: package1: git: url: git://github.com/flutter/packages.git path: packages/package1
上面介紹的這些依賴方式是Flutter開發中經常使用的,但還有一些其它依賴方式,完整的內容讀者能夠自行查看:https://www.dartlang.org/tools/pub/dependencies 。
2.4 資源管理
Flutter APP安裝包中會包含代碼和 assets(資源)兩部分。Assets是會打包到程序安裝包中的,可在運行時訪問。常見類型的assets包括靜態數據(例如JSON文件)、配置文件、圖標和圖片(JPEG,WebP,GIF,動畫WebP / GIF,PNG,BMP和WBMP)等。
指定 assets
和包管理同樣,Flutter也使用pubspec.yaml
(https://www.dartlang.org/tools/pub/pubspec)文件來管理應用程序所需的資源,舉個例子:
flutter: assets: - assets/my_icon.png - assets/background.png
assets
指定應包含在應用程序中的文件, 每一個asset都經過相對於pubspec.yaml
文件所在的文件系統路徑來標識自身的路徑。asset的聲明順序是可有可無的,asset的實際目錄能夠是任意文件夾(在本示例中是assets文件夾)。
在構建期間,Flutter將asset放置到稱爲 asset bundle 的特殊存檔中,應用程序能夠在運行時讀取它們(但不能修改)。
Asset 變體(variant)
構建過程支持「asset變體」的概念:不一樣版本的asset可能會顯示在不一樣的上下文中。在pubspec.yaml
的assets部分中指定asset路徑時,構建過程當中,會在相鄰子目錄中查找具備相同名稱的任何文件。這些文件隨後會與指定的asset一塊兒被包含在asset bundle中。
例如,若是應用程序目錄中有如下文件:
•…/pubspec.yaml•…/graphics/my_icon.png•…/graphics/background.png•…/graphics/dark/background.png•…etc.
而後pubspec.yaml
文件中只需包含:
flutter: assets: - graphics/background.png
那麼這兩個graphics/background.png
和graphics/dark/background.png
都將包含在您的asset bundle中。前者被認爲是main asset (主資源),後者被認爲是一種變體(variant)。
在選擇匹配當前設備分辨率的圖片時,Flutter會使用到asset變體(見下文),未來,Flutter可能會將這種機制擴展到本地化、閱讀提示等方面。
加載 assets
您的應用能夠經過AssetBundle
(https://docs.flutter.io/flutter/services/AssetBundle-class.html)對象訪問其asset 。有兩種主要方法容許從Asset bundle中加載字符串或圖片(二進制)文件。
加載文本assets
•經過
•經過 rootBundle
(https://docs.flutter.io/flutter/services/rootBundle.html)對象, 經過它能夠輕鬆訪問主資源包,直接使用package:flutter/services.dart
中全局靜態的rootBundle
對象來加載asset便可。DefaultAssetBundle
(https://docs.flutter.io/flutter/widgets/DefaultAssetBundle-class.html) 來獲取當前BuildContext的AssetBundle。這種方法不是使用應用程序構建的默認asset bundle,而是使父級widget在運行時動態替換的不一樣的AssetBundle,這對於本地化或測試場景頗有用。
一般,可使用DefaultAssetBundle.of()
在應用運行時來間接加載asset(例如JSON文件),而在widget上下文以外,或其它AssetBundle
句柄不可用時,可使用rootBundle
直接加載這些asset,例如:
import 'dart:async' show Future;import 'package:flutter/services.dart' show rootBundle;
Future<String> loadAsset() async { return await rootBundle.loadString('assets/config.json');}
加載圖片
相似於原生開發,Flutter也能夠爲當前設備加載適合其分辨率的圖像。
聲明分辨率相關的圖片 assets
AssetImage
(https://docs.flutter.io/flutter/painting/AssetImage-class.html) 能夠將asset的請求邏輯映射到最接近當前設備像素比例(dpi)的asset。爲了使這種映射起做用,必須根據特定的目錄結構來保存asset:
•…/image.png•…/Mx/image.png•…/Nx/image.png•…etc.
其中M和N是數字標識符,對應於其中包含的圖像的分辨率,也就是說,它們指定不一樣設備像素比例的圖片。
主資源默認對應於1.0倍的分辨率圖片。看一個例子:
•…/my_icon.png•…/2.0x/my_icon.png•…/3.0x/my_icon.png
在設備像素比率爲1.8的設備上,.../2.0x/my_icon.png
將被選擇。對於2.7的設備像素比率,.../3.0x/my_icon.png
將被選擇。
若是未在Image
widget上指定渲染圖像的寬度和高度,那麼Image
widget將佔用與主資源相同的屏幕空間大小。也就是說,若是.../my_icon.png
是72px乘72px,那麼.../3.0x/my_icon.png
應該是216px乘216px; 但若是未指定寬度和高度,它們都將渲染爲72像素×72像素(以邏輯像素爲單位)。
pubspec.yaml
中asset部分中的每一項都應與實際文件相對應,但主資源項除外。當主資源缺乏某個資源時,會按分辨率從低到高的順序去選擇 ,也就是說1x中沒有的話會在2x中找,2x中尚未的話就在3x中找。
加載圖片
要加載圖片,可使用AssetImage類。例如,咱們能夠從上面的asset聲明中加載背景圖片:
Widget build(BuildContext context) { return new DecoratedBox( decoration: new BoxDecoration( image: new DecorationImage( image: new AssetImage('graphics/background.png'), ), ), );}
注意,AssetImage
並不是是一個widget, 它其實是一個ImageProvider
,有些時候你可能指望直接獲得一個顯示圖片的widget,那麼你可使用Image.asset()
方法,如:
Widget build(BuildContext context) { return Image.asset('graphics/background.png');}
使用默認的 asset bundle 加載資源時,內部會自動處理分辨率等,這些處理對開發者來講是無感知的。(若是使用一些更低級別的類,如 ImageStream或 ImageCache
時你會注意到有與縮放相關的參數)
依賴包中的資源圖片
要加載依賴包中的圖像,必須給AssetImage
提供package
參數。
例如,假設您的應用程序依賴於一個名爲「my_icons」的包,它具備以下目錄結構:
•…/pubspec.yaml•…/icons/heart.png•…/icons/1.5x/heart.png•…/icons/2.0x/heart.png•…etc.
而後加載圖像,使用:
new AssetImage('icons/heart.png', package: 'my_icons')
或
new Image.asset('icons/heart.png', package: 'my_icons')
注意:包在使用自己的資源時也應該加上package
參數來獲取。
打包包中的 assets
若是在pubspec.yaml
文件中聲明瞭指望的資源,它將會打包到相應的package中。特別是,包自己使用的資源必須在pubspec.yaml
中指定。
包也能夠選擇在其lib/
文件夾中包含未在其pubspec.yaml
文件中聲明的資源。在這種狀況下,對於要打包的圖片,應用程序必須在pubspec.yaml
中指定包含哪些圖像。例如,一個名爲「fancy_backgrounds」的包,可能包含如下文件:
•…/lib/backgrounds/background1.png•…/lib/backgrounds/background2.png•…/lib/backgrounds/background3.png
要包含第一張圖像,必須在pubspec.yaml
的assets部分中聲明它:
flutter: assets: - packages/fancy_backgrounds/backgrounds/background1.png
lib/
是隱含的,因此它不該該包含在資產路徑中。
本文分享自微信公衆號 - flutter開發精選(Study_Knowledge)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。