Flutter 知識梳理 (資源加載) - Flutter APK 文件、圖片的加載

在開發Flutter APK時,咱們能夠將一些資源預置在APP中,這些資源能夠分爲如下幾類:app

  • 文本
  • 圖片

爲了統一管理,咱們將它們統一放在assets/目錄下,而後介紹一下如何對它們進行讀取。less

image.png

1、文本

文本通常用於存儲默認數據,在第一次進入無網的狀況下進行數據的展現。async

pubspec.yamlflutter標籤下,聲明要加載的文件名:ide

flutter:

  assets :
    - assets/files/hello.txt
複製代碼

文本的加載有兩種方式:post

  • 使用全局的靜態rootBundle對象,須要導入package:flutter/services.dart,好處是不須要提供BuildContext
  • 使用DefaultAssetBundle獲取當前BuildContextAssetBundle來加載。

兩種方式的示例代碼以下,分別對應於_loadAssetFile()_loadAssetFile2()ui

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(AssetDemo());

class AssetDemo extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Assets Demo')),
        body: AssetFilesWidget(),
      ),
    );
  }

}

class AssetFilesWidget extends StatefulWidget {

  @override
  State<StatefulWidget> createState() {
    return _AssetFilesWidgetState();
  }

}

class _AssetFilesWidgetState extends State<AssetFilesWidget> {

  String text;

  @override
  void initState() {
    super.initState();
    _loadAssetFile2();
  }

  @override
  Widget build(BuildContext context) {
    return Text(text ?? 'default');
  }

  _loadAssetFile() async {
    String text = await rootBundle.loadString('assets/files/hello.txt');
    print(text);
    setState(() {
      this.text = text;
    });
  }

  _loadAssetFile2() async {
    String text = await DefaultAssetBundle.of(context).loadString('assets/files/hello.txt');
    setState(() {
      this.text = text;
    });
  }

}
複製代碼

2、圖片

圖片的加載和文本相似,也是須要先進行聲明再使用。this

Android中,咱們會將圖片放在res/下對應的drawable-?文件夾中,而放在不一樣的文件夾中,根據設備dpi(每英寸圖片上點的個數)的不一樣,最終加載到內存中的圖片大小是不同的,在Flutter中也有相似的概念。spa

關於Android中相關的概念能夠查看這篇文章 圖片基礎知識梳理(2) - Bitmap 佔用內存分析設計

Android 下的目錄

Flutter中,也有和drawable-?相同的設計,用N.X來代替:code

其加載的邏輯爲:

  • 根目錄默認對應於1.0分辨率的圖片。
  • 設備在選擇圖片時,將會選擇離它dpiDensity最近的文件夾。假如dpiDensity=1.8,那麼會選擇2.0x目錄下的資源。(dpiDensityMediaQuery.of(context).devicePixelRatio來獲取。)
  • 肯定了須要選擇哪一個文件夾的圖片後,假如沒有設置Image Widget控件的大小,那麼最終加載顯示的寬高還要用原始圖片寬高再除以對應文件夾的係數。

示例以下: 在pubspec.yaml中聲明:

flutter:

  uses-material-design: true

  assets :
    - assets/files/hello.txt
    - assets/images/
複製代碼

使用Image(key : imageKey, image : AssetImage('assets/images/pic.png'))加載圖片。

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(AssetDemo());

class AssetDemo extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Assets Demo')),
        body: AssetImageWidget(),
      ),
    );
  }

}

class AssetImageWidget extends StatefulWidget {
  
  @override
  State<StatefulWidget> createState() {
    return _AssetImageWidgetState();
  }
  
}

class _AssetImageWidgetState extends State<AssetImageWidget> {
  
  String text;
  GlobalKey imageKey = new GlobalKey();
  
  @override
  Widget build(BuildContext context) {
    return Column(children: <Widget>[
      RaisedButton(onPressed: () {
        text = 'height=${imageKey.currentContext.size.height}'
            ',width=${imageKey.currentContext.size.height}'
            ',dpi=${MediaQuery.of(context).devicePixelRatio}';
        print(text);
      }, child: Text('refresh')),
      Image(key : imageKey, image : AssetImage('assets/images/pic.png'))
    ]);
  }
}
複製代碼

爲了驗證以前的加載邏輯,試驗瞭如下三種狀況:

  • 在主資源assets/images目錄下添加pic.png,結果爲:
height=96.0,width=96.0,dpi=3.0
複製代碼
  • 在主資源和assets/images/3.0x目錄下添加pic.png,結果爲:
height=32.0,width=32.0,dpi=3.0
複製代碼
  • 在主資源和assets/images/2.0x目錄下添加pic.png,結果爲:
height=48.0,width=48.0,dpi=3.0
複製代碼

這裏有點須要注意,當咱們改變資源目錄的結構時,須要修改pubspec.yaml才能生效。

3、使用第三方包中的圖片

3.1 應用程序使用第三方包中的圖片

當應用程序依賴於包名爲my_icons的包,加載圖像的方式爲:

AssetImage('icons/heart.png', package: 'my_icons')
複製代碼

3.2 打包第三方圖片

對於第三方包中的圖片,有如下幾種狀況:

  • 第三方包本身使用的資源,那麼必需要在它自身的pubspec.yaml中聲明,而且使用的時候要帶上本身的包名。
  • 第三方包提供給其它人使用,但自身不使用,分爲兩種狀況:
    • 不管使用者是否用到都強制打包。這種狀況下,第三方包須要在它的pubspec.yaml中聲明,使用者則不須要。
    • 由使用者選擇是否打包。第三方包將資源放在lib/目錄下而且不在pubspec.yaml中聲明,由使用者根據使用狀況在它本身的pubspec.yaml中聲明。

例如第三方包名爲fancy_backgrounds,它的資源有:

…/lib/backgrounds/background1.png
…/lib/backgrounds/background2.png
…/lib/backgrounds/background3.png
複製代碼

假如使用者但願使用background1,那麼就要在它本身的pubspec.yaml中聲明,注意這裏省略了隱式的lib目錄:

flutter:
  assets:
    - packages/fancy_backgrounds/backgrounds/background1.png
複製代碼

參考文章

相關文章
相關標籤/搜索