初略講解Flutter的資源管理

Flutter APP安裝包中會包含代碼和資源(assets)兩部分。assets是會打包到程序安裝包中的,可在運行時訪問。常見類型的assets包括靜態數據(如json文件)、配置文件以及圖標和圖片(JPEG、WebP、GIF、動畫WebP/GIF、PNG、BMP、WBMP)等。html

1、指定assets

和上一節講解包管理同樣,Flutter也是使用pubspec.yaml文件來管理應用程序所需的資源,例如:android

flutter:
    assets:
        - images/my_icon.png
        - images/background.png
複製代碼

針對上述代碼,咱們大體能夠了解到:ios

  • assets指定應包含應用程序中的文件;
  • 每一個asset都經過相對於pubspec.yaml文件所在位置的顯式路徑進行標識;
  • asset的聲明順序是可有可無的;
  • asset的實際目錄能夠是任意文件夾(在本例中是images)

在構建期間,Flutter將asset放置到稱爲asset bundle的特殊存檔中,應用程序能夠在運行時讀取它們(但不能修改)。json

2、asset變體(variant)

應用程序構建過程支持「asset變體」的概念:不一樣版本的asset可能會顯示在不一樣的上下文中。也就是說:在pubspec.yamlassets部分中指定所需的asset的路徑,但在應用程序構建過程當中,會在相鄰子目錄中查找具備相同名稱的任何文件,這些文件隨後會與指定的asset一塊兒被包含在asset bundle中。api

例如,應用程序目錄中有如下文件:bash

  • .../pubspec.yaml
  • .../graphics/my_icon.png
  • .../graphics/background.png
  • .../graphics/dark/background.png
  • ...etc.

上述咱們能夠發現,有兩個graphics/background.pnggraphics/dark/background.png名稱相同但路徑不一樣的圖片文件,接下來咱們在pubspec.yaml文件中只指定:app

flutter:
    assets:
        - graphics/background.png
複製代碼

那麼這兩個graphics/background.pnggraphics/dark/background.png圖片文件,都會在應用程序構建中包含到asset bundle中。前者被認爲main asset(主資源),後者被認爲是一種變體(variant)。框架

在選擇匹配當前設備分辨率的圖片時,Flutter會使用到asset變體,未來Flutter可能會將這種機制擴展到本地化、閱讀提示等方面。async

3、加載assets

應用程序能夠經過AssetBundle對象訪問其asset,有兩種主要方法容許從asset bundle中加載字符串或圖片(二進制)文件。ide

一、加載文本assets

  • 經過rootBundle對象加載:每一個Flutter應用程序都有一個rootBundle對象,經過它能夠輕鬆訪問主資源包,直接使用package:flutter/services.dart中全局靜態的rootBundle對象來加載asset便可。
  • 經過DefaultAssetBundle加載:建議使用DefaultAssetBundle來獲取當前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');
}
複製代碼

二、加載圖片assets

相似於原生開發,Flutter也能夠爲當前設備加載適合其分辨率的圖像。

①、聲明分辨率相關的圖片assets

AssetImage能夠將asset的請求邏輯映射到最接近當前設備像素比例(dpi)的asset,爲了使這種映射起做用,必須根據特定的目錄結構來保存asset:

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

其中M和N是數字標識符,對應於其中包含的圖像的分辨率,也就是說,M和N分別指定不一樣設備像素比例的圖片,例如:

  • .../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將被選擇;而咱們在上面提到的main asset(主資源),它默認對應於1.0倍的分辨率圖片,也就是.../my_icon.png將被選擇。

所以在pubspec.yaml指定asset區域中的每一項都應與實際文件相對應,但main asset(主資源)項除外,由於當主資源缺乏某個資源時,會按分辨率從低到高的順序去選擇,也就說1x中沒有的話會在2x中找,2x中沒有的話就到3x中找。

值得一提的是,若是未在ImageWidget上指定渲染圖像的寬度和高度,那麼ImageWidget將佔用與主資源相同的屏幕空間大小。也就是說,若是.../my_icon.png是72px乘72px,那麼.../3.0x/my_icon.png應該是216px乘216px;但若是未給ImageWidget指定高度和寬度,它們都將渲染爲72px乘72px。

②、加載本地資源圖片

要加載本地圖片,可使用AssetImage類。例如,咱們能夠從上面的asset聲明中加載背景圖片:

Widget build(BuildContext context) {
  return new DecoratedBox(
    decoration: new BoxDecoration(
      image: new DecorationImage(
        image: new AssetImage('graphics/background.png'),
      ),
    ),
  );
}
複製代碼

注意,AssetImage並不是是一個Widget,它其實是一個ImageProvider;不過你可使用Image.asset()方法,直接獲得一個顯示圖片的Widget,例如:

Widget build(BuildContext context) {
  return Image.asset('graphics/background.png');
}
複製代碼

使用默認的asset bundle加載資源時,內部會自動處理分辨率等,這些處理對開發者來講是無感知的(若是使用一些更低級別的類,如ImageStreamImageCache時你會注意到有與縮放相關的參數)。

③、加載依賴包中的資源圖片

要加載依賴包中的圖片,必須給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參數來獲取。

1)、打包包中的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/是隱含的,因此它不該該包含在資產路徑中。

三、特定平臺的assets

上面的資源都是Flutter應用中的,這些資源只有在Flutter框架運行以後才能使用,若是要給咱們的應用設置APP圖標或者添加啓動圖,那咱們必須使用特定平臺的assets。

設置APP圖標

更新Flutter應用程序啓動圖標的方式與在本機Android或iOS應用程序中更新啓動圖標的方式相同。

  • Android

    在Flutter項目的根目錄中,導航到.../android/app/src/main/res目錄,裏面包含了各類資源文件夾(如mipmap-hdpi已包含佔位符圖片ic_launcher_png)。只需按照Android開發人員指南中的說明,將其替換爲所需的資源,並遵照每種屏幕密度(dpi)的建議圖標大小標準。

    注意:若是您重命名.png文件,則還須要在您AndroidManifest.xml<application>標籤的android:icon屬性中更新名稱。

  • iOS

    在Flutter項目的根目錄中,導航到.../ios/Runner/Assets.xcassets/AppIcon.appiconset目錄。該目錄中已包含佔位符圖片,只需將它們替換爲適當大小的圖片,保留原始文件名稱。

添加啓動圖

在Flutter框架加載時,Flutter會使用本地平臺機制繪製啓動頁,此啓動頁將持續到Flutter渲染應用程序的第一幀時。

注意:這意味着若是你不在應用程序的main()方法中調用runApp()函數(或者更具體地說,若是你不調用window.render去響應window.onDrawFrame)的話,啓動頁將永遠持續顯示。

  • Android

    要將啓動屏幕(splash screen)添加到你的Flutter應用程序,請導航到.../android/app/src/main/res/drawable目錄下,在launch_background.xml 文件中,經過自定義drawable來實現自定義啓動界面(也能夠直接換一張圖片)。

  • iOS

    要將圖片添加到啓動屏幕(splash screen)的中心,請導航到.../ios/Runner/Assets.xcassets/LaunchImage.imageset目錄下,拖入圖片並命名爲LaunchImage.pngLaunchImage@2x.pngLaunchImage@3x.png。若是你使用不一樣的文件名,那你還須要更新同一目錄中的Contents.json文件,圖片的具體尺寸能夠查看蘋果官方的標準。

    您也能夠經過打開Xcode徹底自定義storyboard。在Project Navigator中導航到Runner/Runner/Assets.xcassets目錄中,拖入圖片,或者經過在LaunchScreen.storyboard中使用Interface Builder進行自定義。

相關文章
相關標籤/搜索