以前的章節咱們基本上把Flutter中基礎部分的東西都作了簡單的講解,經過前面章節的循序學習讀者也基本能完成一些簡單的UI繪製並能利用Flutter處理一些簡單的用戶交互,讀者可能也留意到,咱們以前的章節中所學習到的內容並無涉及到數據存儲方面的操做,或者說,咱們到如今爲止並不知道在Flutter中數據應該怎麼存,存在哪。本篇博文中筆者將會爲你們解決這一疑惑。java
相信作過原生Android開發的讀者對數據存儲並不陌生,在原生Android中咱們會把一些輕量級的數據(如用戶信息、APP配置信息等)寫入SharedPreferences
作存儲,把須要長期存儲的數據寫入本地文件或者Sqlite3
,固然Flutter中也一樣用一套完整的本地數據存儲體系,下面咱們就一直來了解下上述提到的這3中本地存儲方式在Flutter中使用。ios
在Flutter中自己並無內置SharedPreferences存儲,可是官方給咱們提供了第三方的組件來實現這一存儲方式。咱們能夠經過pubspec.yaml
文件引入,關於pubspec.yaml
的使用咱們在Flutter入門進階之旅(五)Image Widget,這一章節提到過,只不過在Image使用中咱們引入的是assets
文件依賴。數據庫
以下咱們在dependencies節點下引入SharedPreferences的依賴,讀者在pubspec.yaml引入依賴時必定要注意代碼縮進格式,不然在在執行flutter packages get時極可能會報錯
。緩存
dependencies:
flutter:
sdk: flutter
# 添加sharedPreference依賴
shared_preferences: ^0.5.0
dev_dependencies:
flutter_test:
sdk: flutter
# 引入本地資源圖片
assets:
- images/a.png
- images/aaa.png
複製代碼
而後命令行執行flutter packages get
把遠程依賴同步到本地,在此筆者寫文章的時候sharedPreference的最新版本是0.5.0,讀者可自行去pub.dartlang.org/flutter上獲取最新版本,同時也能夠在上面找到其餘須要引入的資源依賴包。app
筆者的話async
囉裏囉嗦的準備工做總算是講完了,主要是今天的課程涉及到了包依賴管理,可能對於有些初學者有點懵,因此我就藉助sharedPreference把依賴引入廢話扯了一大通,若是讀者已經掌握了上述操做,可跳過準備工做直接到下面的部分。ide
繼續上面的內容,咱們先來體驗一下sharedPreference,貼個圖你們放鬆一下。 學習
從上圖中咱們看到咱們使用sharedPreference
作了簡單存儲跟獲取的操做,其實sharedPreference
好像也就這麼點左右,不是存就是取。讀者在自行操做時必定不要忘記導入sharedPreference
的包ui
import 'package:shared_preferences/shared_preferences.dart';
複製代碼
跟原生Android同樣,Flutter中操做sp也是經過key-value的方式存取數據spa
/** * 利用SharedPreferences存儲數據 */
Future saveString() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setString(
STORAGE_KEY, _textFieldController.value.text.toString());
}
複製代碼
SharedPreferences
中爲咱們提供了String、bool、Double、Int、StringList數據類型的存取。
/** * 獲取存在SharedPreferences中的數據 */
Future getString() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
setState(() {
_storageString = sharedPreferences.get(STORAGE_KEY);
});
}
複製代碼
上述操做邏輯中咱們經過_textFieldController
獲取在TextField
中的值,在按下存儲按鈕的同時咱們把數據寫入sp中,當按下獲取值的時候咱們經過setState
把從sp中獲取的值同步更新到下面的Text上顯示。
完整代碼:
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class StoragePage extends StatefulWidget {
@override
State<StatefulWidget> createState() => StorageState();
}
class StorageState extends State {
var _textFieldController = new TextEditingController();
var _storageString = '';
final STORAGE_KEY = 'storage_key';
/** * 利用SharedPreferences存儲數據 */
Future saveString() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setString(
STORAGE_KEY, _textFieldController.value.text.toString());
}
/** * 獲取存在SharedPreferences中的數據 */
Future getString() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
setState(() {
_storageString = sharedPreferences.get(STORAGE_KEY);
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('數據存儲'),
),
body: new Column(
children: <Widget>[
Text("shared_preferences存儲", textAlign: TextAlign.center),
TextField(
controller: _textFieldController,
),
MaterialButton(
onPressed: saveString,
child: new Text("存儲"),
color: Colors.pink,
),
MaterialButton(
onPressed: getString,
child: new Text("獲取"),
color: Colors.lightGreen,
),
Text('shared_preferences存儲的值爲 $_storageString'),
],
),
);
}
}
複製代碼
雖然咱們今天內容是Flutter的數據存儲,尷尬的是Flutter自己都沒有內置提到的這三種存儲方式,不過好在官方給咱們提供了三方的支持庫,不知道後續的Flutter版本中會不會對此作改進。操做文件一樣咱們也須要像SharedPreferences同樣,須要在pubspec.yaml
引入。在 Flutter 裏實現文件讀寫,須要使用 path_provider 和 dart 的 io 模塊。path_provider 負責查找 iOS/Android 的目錄文件,IO 模塊負責對文件進行讀寫
# 添加文件依賴
path_provider: ^0.5.0
複製代碼
筆者在此引入的最新版本是0.5.0,讀者可自行去pub.dartlang.org/flutter上獲取最新版本。
因爲整個操做演示邏輯跟SharedPreferences同樣,我就不詳細講解文件存儲中關於存取數據的具體操做了,稍微我貼上源代碼,讀者自行查閱代碼對比便可,關於文件存儲的三個獲取文件路徑的方法我這裏說明一下,作過原生Android開發的讀者可能對此不陌生,可是ios或者初學者可能並不瞭解這個概念,因此我想提出來講明一下。
在path_provider中有三個獲取文件路徑的方法:
getTemporaryDirectory()//獲取應用緩存目錄,等同IOS的NSTemporaryDirectory()和Android的getCacheDir() 方法
getApplicationDocumentsDirectory()獲取應用文件目錄相似於Ios的NSDocumentDirectory和Android上的 AppData目錄
getExternalStorageDirectory()//這個是存儲卡,僅僅在Android平臺可使用
來看下操做文件的效果圖:
借用了SharedPreferences存儲的邏輯,只是把存儲的代碼放在了file.text
中,代碼裏有詳盡的註釋,我就很少作解釋說明了,讀者可自行嘗試對比跟SharedPreferences
的差異
樣例代碼
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
class StoragePage extends StatefulWidget {
@override
State<StatefulWidget> createState() => StorageState();
}
class StorageState extends State {
var _textFieldController = new TextEditingController();
var _storageString = '';
/** * 利用文件存儲數據 */
saveString() async {
final file = await getFile('file.text');
//寫入字符串
file.writeAsString(_textFieldController.value.text.toString());
}
/** * 獲取存在文件中的數據 */
Future getString() async {
final file = await getFile('file.text');
var filePath = file.path;
setState(() {
file.readAsString().then((String value) {
_storageString = value +'\n文件存儲路徑:'+filePath;
});
});
}
/** * 初始化文件路徑 */
Future<File> getFile(String fileName) async {
//獲取應用文件目錄相似於Ios的NSDocumentDirectory和Android上的 AppData目錄
final fileDirectory = await getApplicationDocumentsDirectory();
//獲取存儲路徑
final filePath = fileDirectory.path;
//或者file對象(操做文件記得導入import 'dart:io')
return new File(filePath + "/"+fileName);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('數據存儲'),
),
body: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("文件存儲", textAlign: TextAlign.center),
TextField(
controller: _textFieldController,
),
MaterialButton(
onPressed: saveString,
child: new Text("存儲"),
color: Colors.cyan,
),
MaterialButton(
onPressed: getString,
child: new Text("獲取"),
color: Colors.deepOrange,
),
Text('從文件存儲中獲取的值爲 $_storageString'),
],
),
);
}
}
複製代碼
在Flutter中的數據庫叫Sqflite
跟原生安卓的Sqlite
叫法不同。咱們來看下Sqflite
官方對它的解釋說明:
SQLite plugin for Flutter. Supports both iOS and Android.
Support transactions and batches
Automatic version managment during open
Helpers for insert/query/update/delete queries
DB operation executed in a background thread on iOS and Android
複製代碼
經過上面的描述,咱們瞭解到Sqflite
是一個同時支持Android跟Ios平臺的數據庫,而且支持標準的CURD
操做,下面咱們仍是用上面操做文件跟sp的代碼邏輯是一塊體驗一下Sqflite
。
一樣須要引入依賴:
#添加Sqflite依賴
sqflite: ^1.0.0
複製代碼
模擬場景:
利用Sqflite建立一張user表,其中user表中id設置爲主鍵id,且爲自增加,name字段爲text類型,用戶按下存儲按鈕後,把TextFile輸入框裏的內容插入到user表中,當按下獲取按鈕時,取出數據庫中最後一條數據顯示在下方Text上,而且顯示出當前數據庫中一共有多少條數據,以及數據庫的存儲路徑。
效果圖
上述描述樣式代碼import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
import 'package:sqflite/sqflite.dart';
class StoragePage extends StatefulWidget {
@override
State<StatefulWidget> createState() => StorageState();
}
class StorageState extends State {
var _textFieldController = new TextEditingController();
var _storageString = '';
/** * 利用Sqflite數據庫存儲數據 */
saveString() async {
final db = await getDataBase('my_db.db');
//寫入字符串
db.transaction((trx) {
trx.rawInsert(
'INSERT INTO user(name) VALUES("${_textFieldController.value.text.toString()}")');
});
}
/** * 獲取存在Sqflite數據庫中的數據 */
Future getString() async {
final db = await getDataBase('my_db.db');
var dbPath = db.path;
setState(() {
db.rawQuery('SELECT * FROM user').then((List<Map> lists) {
print('----------------$lists');
var listSize = lists.length;
//獲取數據庫中的最後一條數據
_storageString = lists[listSize - 1]['name'] +
"\n如今數據庫中一共有${listSize}條數據" +
"\n數據庫的存儲路徑爲${dbPath}";
});
});
}
/** * 初始化數據庫存儲路徑 */
Future<Database> getDataBase(String dbName) async {
//獲取應用文件目錄相似於Ios的NSDocumentDirectory和Android上的 AppData目錄
final fileDirectory = await getApplicationDocumentsDirectory();
//獲取存儲路徑
final dbPath = fileDirectory.path;
//構建數據庫對象
Database database = await openDatabase(dbPath + "/" + dbName, version: 1, onCreate: (Database db, int version) async {
await db.execute("CREATE TABLE user (id INTEGER PRIMARY KEY, name TEXT)");
});
return database;
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('數據存儲'),
),
body: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Sqflite數據庫存儲", textAlign: TextAlign.center),
TextField(
controller: _textFieldController,
),
MaterialButton(
onPressed: saveString,
child: new Text("存儲"),
color: Colors.cyan,
),
MaterialButton(
onPressed: getString,
child: new Text("獲取"),
color: Colors.deepOrange,
),
Text('從Sqflite數據庫中獲取的值爲 $_storageString'),
],
),
);
}
}
複製代碼
至此,關於Flutter的本地存儲相關的內容就所有講解完了,在本文章中,我爲了清晰代碼結構跟業務邏輯,複用的都是同一個存儲業務邏輯跟UI便於你們結合代碼作對比,讀者可結合代碼自行對比三種存儲方式的細節差異。