在開發Flutter APK
時,咱們能夠將一些資源預置在APP
中,這些資源能夠分爲如下幾類:app
爲了統一管理,咱們將它們統一放在assets/
目錄下,而後介紹一下如何對它們進行讀取。less
文本通常用於存儲默認數據,在第一次進入無網的狀況下進行數據的展現。async
在pubspec.yaml
的flutter
標籤下,聲明要加載的文件名:ide
flutter:
assets :
- assets/files/hello.txt
複製代碼
文本的加載有兩種方式:post
rootBundle
對象,須要導入package:flutter/services.dart
,好處是不須要提供BuildContext
。DefaultAssetBundle
獲取當前BuildContext
的AssetBundle
來加載。兩種方式的示例代碼以下,分別對應於_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;
});
}
}
複製代碼
圖片的加載和文本相似,也是須要先進行聲明再使用。this
在Android
中,咱們會將圖片放在res/
下對應的drawable-?
文件夾中,而放在不一樣的文件夾中,根據設備dpi
(每英寸圖片上點的個數)的不一樣,最終加載到內存中的圖片大小是不同的,在Flutter
中也有相似的概念。spa
關於Android
中相關的概念能夠查看這篇文章 圖片基礎知識梳理(2) - Bitmap 佔用內存分析。設計
在Flutter
中,也有和drawable-?
相同的設計,用N.X
來代替:code
其加載的邏輯爲:
1.0
分辨率的圖片。dpiDensity
最近的文件夾。假如dpiDensity=1.8
,那麼會選擇2.0x
目錄下的資源。(dpiDensity
用MediaQuery.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
才能生效。
當應用程序依賴於包名爲my_icons
的包,加載圖像的方式爲:
AssetImage('icons/heart.png', package: 'my_icons')
複製代碼
對於第三方包中的圖片,有如下幾種狀況:
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
複製代碼