Flutter實戰(zhàn) 資源管理

2021-03-06 16:26 更新

Flutter APP 安裝包中會包含代碼和 assets(資源)兩部分。Assets 是會打包到程序安裝包中的,可在運行時訪問。常見類型的 assets 包括靜態(tài)數(shù)據(jù)(例如 JSON 文件)、配置文件、圖標(biāo)和圖片(JPEG,WebP,GIF,動畫 WebP / GIF,PNG,BMP 和 WBMP)等。

#指定 assets

和包管理一樣,F(xiàn)lutter 也使用pubspec.yaml (opens new window)文件來管理應(yīng)用程序所需的資源,舉個例子:

flutter:
  assets:
    - assets/my_icon.png
    - assets/background.png

assets指定應(yīng)包含在應(yīng)用程序中的文件, 每個 asset 都通過相對于pubspec.yaml文件所在的文件系統(tǒng)路徑來標(biāo)識自身的路徑。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.pnggraphics/dark/background.png 都將包含在您的 asset bundle 中。前者被認(rèn)為是main asset (主資源),后者被認(rèn)為是一種變體(variant)。

在選擇匹配當(dāng)前設(shè)備分辨率的圖片時,F(xiàn)lutter 會使用到 asset 變體(見下文),將來,F(xiàn)lutter 可能會將這種機制擴展到本地化、閱讀提示等方面。

#加載 assets

您的應(yīng)用可以通過AssetBundle (opens new window)對象訪問其 asset 。有兩種主要方法允許從 Asset bundle 中加載字符串或圖片(二進制)文件。

#加載文本assets

  • 通過rootBundle (opens new window)對象加載:每個Flutter應(yīng)用程序都有一個rootBundle (opens new window)對象, 通過它可以輕松訪問主資源包,直接使用package:flutter/services.dart中全局靜態(tài)的rootBundle對象來加載asset即可。
  • 通過 DefaultAssetBundle (opens new window)加載:建議使用 DefaultAssetBundle (opens new window)來獲取當(dāng)前 BuildContext 的 AssetBundle。 這種方法不是使用應(yīng)用程序構(gòu)建的默認(rèn) asset bundle,而是使父級 widget 在運行時動態(tài)替換的不同的 AssetBundle,這對于本地化或測試場景很有用。

通常,可以使用DefaultAssetBundle.of()在應(yīng)用運行時來間接加載 sset(例如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也可以為當(dāng)前設(shè)備加載適合其分辨率的圖像。

#聲明分辨率相關(guān)的圖片 assets

AssetImage (opens new window)可以將 asset 的請求邏輯映射到最接近當(dāng)前設(shè)備像素比例(dpi)的 asset。為了使這種映射起作用,必須根據(jù)特定的目錄結(jié)構(gòu)來保存 asset:

  • …/image.png
  • …/Mx/image.png
  • …/Nx/image.png
  • …etc.

其中M和N是數(shù)字標(biāo)識符,對應(yīng)于其中包含的圖像的分辨率,也就是說,它們指定不同設(shè)備像素比例的圖片。

主資源默認(rèn)對應(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),但主資源項除外。當(dāng)主資源缺少某個資源時,會按分辨率從低到高的順序去選擇 ,也就是說1x中沒有的話會在2x中找,2x中還沒有的話就在3x中找。

#加載圖片

要加載圖片,可以使用 AssetImage (opens new window)類。例如,我們可以從上面的 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');
}

使用默認(rèn)的 asset bundle 加載資源時,內(nèi)部會自動處理分辨率等,這些處理對開發(fā)者來說是無感知的。 (如果使用一些更低級別的類,如 ImageStream (opens new window)或 ImageCache (opens new window)時你會注意到有與縮放相關(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)路徑中。

#特定平臺 assets

上面的資源都是 flutter 應(yīng)用中的,這些資源只有在 Flutter 框架運行之后才能使用,如果要給我們的應(yīng)用設(shè)置 APP 圖標(biāo)或者添加啟動圖,那我們必須使用特定平臺的 assets。

#設(shè)置APP圖標(biāo)

更新 Flutter 應(yīng)用程序啟動圖標(biāo)的方式與在本機 Android 或 iOS 應(yīng)用程序中更新啟動圖標(biāo)的方式相同。

  • Android

在 Flutter 項目的根目錄中,導(dǎo)航到.../android/app/src/main/res目錄,里面包含了各種資源文件夾(如mipmap-hdpi已包含占位符圖像“ic_launcher.png”,見圖2-8)。 只需按照Android開發(fā)人員指南 (opens new window)中的說明, 將其替換為所需的資源,并遵守每種屏幕密度(dpi)的建議圖標(biāo)大小標(biāo)準(zhǔn)。

圖2-8

注意: 如果您重命名.png文件,則還必須在您AndroidManifest.xml<application&標(biāo)簽的android:icon屬性中更新名稱。

  • iOS

在 Flutter 項目的根目錄中,導(dǎo)航到.../ios/Runner。該目錄中Assets.xcassets/AppIcon.appiconset已經(jīng)包含占位符圖片(見圖2-9), 只需將它們替換為適當(dāng)大小的圖片,保留原始文件名稱。

圖2-9

#更新啟動頁

圖2-10

在 Flutter 框架加載時,F(xiàn)lutter 會使用本地平臺機制繪制啟動頁。此啟動頁將持續(xù)到 Flutter 渲染應(yīng)用程序的第一幀時。

注意: 這意味著如果您不在應(yīng)用程序的main()方法中調(diào)用 runApp (opens new window)函數(shù) (或者更具體地說,如果您不調(diào)用window.render (opens new window)去響應(yīng)window.onDrawFrame (opens new window)的話, 啟動屏幕將永遠(yuǎn)持續(xù)顯示。

#Android

要將啟動屏幕(splash screen)添加到您的 Flutter 應(yīng)用程序, 請導(dǎo)航至.../android/app/src/main。在res/drawable/launch_background.xml,通過自定義 drawable 來實現(xiàn)自定義啟動界面(你也可以直接換一張圖片)。

#iOS

要將圖片添加到啟動屏幕(splash screen)的中心,請導(dǎo)航至.../ios/Runner。在Assets.xcassets/LaunchImage.imageset, 拖入圖片,并命名為LaunchImage.png、LaunchImage@2x.pngLaunchImage@3x.png。 如果你使用不同的文件名,那您還必須更新同一目錄中的Contents.json文件,圖片的具體尺寸可以查看蘋果官方的標(biāo)準(zhǔn)。

您也可以通過打開 Xcode 完全自定義storyboard。在 Project Navigator 中導(dǎo)航到Runner/Runner然后通過打開Assets.xcassets拖入圖片,或者通過在 LaunchScreen.storyboard 中使用 Interface Builder 進行自定義,如圖2-11所示。

圖2-11

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號