資源管理
Flutter APP安裝包中會包含代碼和 assets(資源)兩部分。Assets是會打包到程序安裝包中的,可在運行時訪問。常見類型的assets包括靜態(tài)數(shù)據(jù)(例如JSON文件)、配置文件、圖標和圖片(JPEG,WebP,GIF,動畫WebP / GIF,PNG,BMP和WBMP)等。
指定 assets
和包管理一樣,F(xiàn)lutter也使用pubspec.yaml文件來管理應(yīng)用程序所需的資源,舉個例子:(圖片名字便于區(qū)分隨便寫的)
flutter:
assets:
- assets/image/jisuan.png
- assets/image/qianbao.png
assets指定應(yīng)包含在應(yīng)用程序中的文件, 每個asset都通過相對于pubspec.yaml文件所在的文件系統(tǒng)路徑來標識自身的路徑。asset的聲明順序是無關(guān)緊要的,asset的實際目錄可以是任意文件夾(在本示例中是assets文件夾)。
在構(gòu)建期間,F(xiàn)lutter將asset放置到稱為 asset bundle 的特殊存檔中,應(yīng)用程序可以在運行時讀取它們(但不能修改)。
Asset 變體(variant)
構(gòu)建過程支持“asset變體”的概念:不同版本的asset可能會顯示在不同的上下文中。 在pubspec.yaml的assets部分中指定asset路徑時,構(gòu)建過程中,會在相鄰子目錄中查找具有相同名稱的任何文件。這些文件隨后會與指定的asset一起被包含在asset bundle中。
例如,如果應(yīng)用程序目錄中有以下文件:
…/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)。
在選擇匹配當前設(shè)備分辨率的圖片時,F(xiàn)lutter會使用到asset變體(見下文),將來,F(xiàn)lutter可能會將這種機制擴展到本地化、閱讀提示等方面
加載 assets
- 通過
rootBundle對象加載:每個Flutter應(yīng)用程序都有一個rootBundle對象, 通過它可以輕松訪問主資源包,直接使用package:flutter/services.dart中全局靜態(tài)的rootBundle對象來加載asset即可。 - 通過
DefaultAssetBundle加載:建議使用DefaultAssetBundle來獲取當前BuildContext的AssetBundle。 這種方法不是使用應(yīng)用程序構(gòu)建的默認asset bundle,而是使父級widget在運行時動態(tài)替換的不同的AssetBundle,這對于本地化或測試場景很有用。
通常,可以使用DefaultAssetBundle.of()在應(yīng)用運行時來間接加載asset(例如JSON文件),而在widget上下文之外,或其它AssetBundle句柄不可用時,可以使用rootBundle直接加載這些asset,例如:
- 通過
rootBundle對象加載:每個Flutter應(yīng)用程序都有一個rootBundle對象, 通過它可以輕松訪問主資源包,直接使用package:flutter/services.dart中全局靜態(tài)的rootBundle對象來加載asset即可。 - 通過
DefaultAssetBundle加載:建議使用DefaultAssetBundle來獲取當前BuildContext的AssetBundle。 這種方法不是使用應(yīng)用程序構(gòu)建的默認asset bundle,而是使父級widget在運行時動態(tài)替換的不同的AssetBundle,這對于本地化或測試場景很有用。
通常,可以使用DefaultAssetBundle.of()在應(yīng)用運行時來間接加載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');
}
加載圖片
類似于原生開發(fā),F(xiàn)lutter也可以為當前設(shè)備加載適合其分辨率的圖像。
聲明分辨率相關(guān)的圖片 assets
AssetImage 可以將asset的請求邏輯映射到最接近當前設(shè)備像素比例(dpi)的asset。為了使這種映射起作用,必須根據(jù)特定的目錄結(jié)構(gòu)來保存asset:
- …/image.png
- …/Mx/image.png
- …/Nx/image.png
- …etc.
其中M和N是數(shù)字標識符,對應(yīng)于其中包含的圖像的分辨率,也就是說,它們指定不同設(shè)備像素比例的圖片。
主資源默認對應(yīng)于1.0倍的分辨率圖片??匆粋€例子:
- …/my_icon.png
- …/2.0x/my_icon.png
- …/3.0x/my_icon.png
在設(shè)備像素比率為1.8的設(shè)備上,.../2.0x/my_icon.png 將被選擇。對于2.7的設(shè)備像素比率,.../3.0x/my_icon.png將被選擇。
如果未在Image widget上指定渲染圖像的寬度和高度,那么Image widget將占用與主資源相同的屏幕空間大小。 也就是說,如果.../my_icon.png是72px乘72px,那么.../3.0x/my_icon.png應(yīng)該是216px乘216px; 但如果未指定寬度和高度,它們都將渲染為72像素×72像素(以邏輯像素為單位)。
pubspec.yaml中asset部分中的每一項都應(yīng)與實際文件相對應(yīng),但主資源項除外。當主資源缺少某個資源時,會按分辨率從低到高的順序去選擇 ,也就是說1x中沒有的話會在2x中找,2x中還沒有的話就在3x中找。
看下在iphone 11 pro max和iphone8上的運行效果

2.0x文件夾中的jisuan圖片樣式是

3.0x文件夾中的jisuan圖片樣式是

iphone8上顯示

iphone11 pro max上顯示

項目中有的不需要1.0x的圖, 只有2.0x和3.0x的圖,我們pubspec.yaml中寫資源路徑是直接寫相應(yīng)路徑就好了, 忽略2.0x 3.0x文件夾

加載圖片
要加載圖片,可以使用 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 加載資源時,內(nèi)部會自動處理分辨率等,這些處理對開發(fā)者來說是無感知的。 (如果使用一些更低級別的類,如 ImageStream或 ImageCache 時你會注意到有與縮放相關(guān)的參數(shù))
依賴包中的資源圖片
要加載依賴包中的圖像,必須給AssetImage提供package參數(shù)。
例如,假設(shè)您的應(yīng)用程序依賴于一個名為“my_icons”的包,它具有如下目錄結(jié)構(gòu):
- …/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')
注意:包在使用本身的資源時也應(yīng)該加上package參數(shù)來獲取。
打包包中的 assets
如果在pubspec.yaml文件中聲明了期望的資源,它將會打包到相應(yīng)的package中。特別是,包本身使用的資源必須在pubspec.yaml中指定。
包也可以選擇在其lib/文件夾中包含未在其pubspec.yaml文件中聲明的資源。在這種情況下,對于要打包的圖片,應(yīng)用程序必須在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/是隱含的,所以它不應(yīng)該包含在資產(chǎn)路徑中。