## 文件操作
Dart的IO庫包含了文件讀寫的相關類,它屬于Dart語法標準的一部分,所以通過Dart IO庫,無論是Dart VM下的腳本還是Flutter,都是通過Dart IO庫來操作文件的,不過和Dart VM相比,Flutter有一個重要差異是文件系統路徑不同,這是因為Dart VM是運行在PC或服務器操作系統下,而Flutter是運行在移動操作系統中,他們的文件系統會有一些差異。
#### APP目錄
Android和iOS的應用存儲目錄不同,[`PathProvider`](https://pub.dartlang.org/packages/path_provider) 插件提供了一種平臺透明的方式來訪問設備文件系統上的常用位置。該類當前支持訪問兩個文件系統位置:
- **臨時目錄:** 可以使用 `getTemporaryDirectory()` 來獲取臨時目錄; 系統可隨時清除的臨時目錄(緩存)。在iOS上,這對應于[`NSTemporaryDirectory()`](https://developer.apple.com/reference/foundation/1409211-nstemporarydirectory) 返回的值。在Android上,這是[`getCacheDir()`](https://developer.android.com/reference/android/content/Context.html#getCacheDir())返回的值。
- **文檔目錄:** 可以使用`getApplicationDocumentsDirectory()`來獲取應用程序的文檔目錄,該目錄用于存儲只有自己可以訪問的文件。只有當應用程序被卸載時,系統才會清除該目錄。在iOS上,這對應于`NSDocumentDirectory`。在Android上,這是`AppData`目錄。
- **外部存儲目錄**:可以使用`getExternalStorageDirectory()`來獲取外部存儲目錄,如SD卡;由于iOS不支持外部目錄,所以在iOS下調用該方法會拋出`UnsupportedError`異常,而在Android下結果是android SDK中`getExternalStorageDirectory`的返回值。
一旦你的Flutter應用程序有一個文件位置的引用,你可以使用[dart:io](https://api.dartlang.org/stable/dart-io/dart-io-library.html)API來執行對文件系統的讀/寫操作。有關使用Dart處理文件和目錄的詳細內容可以參考Dart語言文檔,下面我們看一個簡單的例子。
#### 示例
我們還是以計數器為例,實現在應用退出重啟后可以恢復點擊次數。 這里,我們使用文件來保存數據:
1. 引入PathProvider插件;在`pubspec.yaml`文件中添加如下聲明:
```
path_provider: ^0.4.1
```
添加后,執行`flutter packages get` 獲取一下, 版本號可能隨著時間推移會發生變化,讀者可以使用最新版。
2. 實現:
```
import 'dart:io';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
class FileOperationRoute extends StatefulWidget {
FileOperationRoute({Key key}) : super(key: key);
@override
_FileOperationRouteState createState() => new _FileOperationRouteState();
}
class _FileOperationRouteState extends State<FileOperationRoute> {
int _counter;
@override
void initState() {
super.initState();
//從文件讀取點擊次數
_readCounter().then((int value) {
setState(() {
_counter = value;
});
});
}
Future<File> _getLocalFile() async {
// 獲取應用目錄
String dir = (await getApplicationDocumentsDirectory()).path;
return new File('$dir/counter.txt');
}
Future<int> _readCounter() async {
try {
File file = await _getLocalFile();
// 讀取點擊次數(以字符串)
String contents = await file.readAsString();
return int.parse(contents);
} on FileSystemException {
return 0;
}
}
Future<Null> _incrementCounter() async {
setState(() {
_counter++;
});
// 將點擊次數以字符串類型寫到文件中
await (await _getLocalFile()).writeAsString('$_counter');
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('文件操作')),
body: new Center(
child: new Text('點擊了 $_counter 次'),
),
floatingActionButton: new FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: new Icon(Icons.add),
),
);
}
}
```
上面代碼比較簡單,不再贅述,需要說明的是,本示例只是為了演示文件讀寫,而在實際開發中,如果要存儲一些簡單的數據,使用shared\_preferences插件會比較簡單。
> 注意,Dart IO庫操作文件的API非常豐富,但本書不是介紹Dart語言的,故不詳細說明,讀者需要的話可以自行學習。
- 緣起
- 起步
- 移動開發技術簡介
- Flutter簡介
- 搭建Flutter開發環境
- 常見配置問題
- Dart語言簡介
- 第一個Flutter應用
- 計數器示例
- 路由管理
- 包管理
- 資源管理
- 調試Flutter APP
- Dart線程模型及異常捕獲
- 基礎Widgets
- Widget簡介
- 文本、字體樣式
- 按鈕
- 圖片和Icon
- 單選框和復選框
- 輸入框和表單
- 布局類Widgets
- 布局類Widgets簡介
- 線性布局Row、Column
- 彈性布局Flex
- 流式布局Wrap、Flow
- 層疊布局Stack、Positioned
- 容器類Widgets
- Padding
- 布局限制類容器ConstrainedBox、SizeBox
- 裝飾容器DecoratedBox
- 變換Transform
- Container容器
- Scaffold、TabBar、底部導航
- 可滾動Widgets
- 可滾動Widgets簡介
- SingleChildScrollView
- ListView
- GridView
- CustomScrollView
- 滾動監聽及控制ScrollController
- 功能型Widgets
- 導航返回攔截-WillPopScope
- 數據共享-InheritedWidget
- 主題-Theme
- 事件處理與通知
- 原始指針事件處理
- 手勢識別
- 全局事件總線
- 通知Notification
- 動畫
- Flutter動畫簡介
- 動畫結構
- 自定義路由過渡動畫
- Hero動畫
- 交錯動畫
- 自定義Widget
- 自定義Widget方法簡介
- 通過組合現有Widget實現
- 實例:TurnBox
- CustomPaint與Canvas
- 實例:圓形漸變進度條(自繪)
- 文件操作與網絡請求
- 文件操作
- Http請求-HttpClient
- Http請求-Dio package
- 實例:Http分塊下載
- WebSocket
- 使用Socket API
- Json轉Model
- 包與插件
- 開發package
- 插件開發:平臺通道簡介
- 插件開發:實現Android端API
- 插件開發:實現IOS端API
- 系統能力調用
- 國際化
- 讓App支持多語言
- 實現Localizations
- 使用Intl包
- Flutter核心原理
- Flutter UI系統
- Element和BuildContext
- RenderObject與RenderBox
- Flutter從啟動到顯示