咱們在作APP開發時, 常常會涉及到用戶數據的存儲(好比保存用戶登陸token、用戶的某些偏好設置等). 開發過Android的朋友應該知道有 SharedPreferences. 在 Flutter 中, 一樣爲咱們提供了十分類似的(甚至名字都同樣)組件, 爲咱們提供數據存儲的能力. git
本篇教程將用一個簡單的小Demo, 讓你徹底掌握 數據存儲之SharedPreferences 的用法.github
若圖片展現異常, 請訪問個人 官方博客
有圖有真相, 咱們先來看一下咱們最終的效果:bash
全部源碼(含註釋)均已上傳至開源倉庫:app
本博客的環境一覽:less
環境 | 版本號 |
---|---|
Flutter | 1.14.6 beta |
Dart | 2.8.0-dev.5.0 |
Android Studio | 3.5.2 |
注意您的環境和文中的差別, 避免出現不兼容的狀況哦!
要順利閱讀本文, 假定您已經具有如下條件:異步
Android Studio
或 VSCode
(或任何你喜歡的代碼編輯器).Flutter
開發環境.Flutter
的開發基礎(至少了解目錄結構、Dart
語言基本知識).建立一個新的Flutter項目, 命名爲my_shared_preferences_demo
(您能夠隨意起名, 可是在下面也要替換名字爲您本身的).async
注意: Flutter項目名不要和引入的某個第三方庫重名, 不然會報:
A package may not list itself as a dependency
代碼截圖:編輯器
由於咱們的項目過於簡單, 暫時不須要進行測試. 刪除./test目錄:ide
避免冗餘代碼誤導咱們, 替換./lib/main.dart
爲:函數
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'SharedPreferences Demo', home: MyHomePage(title: 'SharedPreferences Demo Page'), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[], ), ), ); } }
進入./pubspec.yaml
, 添加依賴:
dependencies: shared_preferences: ^0.5.6+3
你也能夠去官網查看 最新的shared_preferences
截圖:
更新包, 在終端中輸入(或者點擊IDE的更新包的按鈕):
flutter packages get
運行項目:
如今, 咱們能夠正式進行數據存儲的操做了!
實際項目中, 咱們定會屢次用到數據的讀寫, 因此封裝一個工具類是比較明智的選擇.
建立./lib/shared_preferences_util.dart
SharedPreferencesUtil
類class SharedPreferencesUtil { }
由於後面要用到SharedPreferences, 因此導入shared_preferences:
import 'package:shared_preferences/shared_preferences.dart';
saveData()
添加函數saveData()
:
/// 保存數據 static saveData<T>(String key, T value) async { SharedPreferences prefs = await SharedPreferences.getInstance(); switch (T) { case String: prefs.setString(key, value as String); break; case int: prefs.setInt(key, value as int); break; case bool: prefs.setBool(key, value as bool); break; case double: prefs.setDouble(key, value as double); break; } }
在定義函數時, 名稱後面多了一個"<T>
", 這運用了泛型. 若對此有疑問, 請自行搜索"dart 泛型"的相關知識.代碼解析: 函數要求傳入兩個值, key以及value. key爲咱們要存的值的"名字". 這個名字是惟一的, 後續咱們在讀取數據的時候也須要傳入與這個key. value就是它對應的值. 函數體內, 咱們先在首行引入一個SharedPreferences的實例, 便於後續使用. 使用
switch
分支, 用來判斷傳入的泛型類型. 判斷完成後, 分別調用prefs.setXXX(key, value)
, 完成數據存儲.
代碼截圖:
getData()
有數據存儲函數, 天然也應該有與之對應的數據讀取函數, 咱們來寫:
添加函數getData()
:
/// 讀取數據 static Future<T> getData<T>(String key) async { SharedPreferences prefs = await SharedPreferences.getInstance(); T res; switch (T) { case String: res = prefs.getString(key) as T; break; case int: res = prefs.getInt(key) as T; break; case bool: res = prefs.getBool(key) as T; break; case double: res = prefs.getDouble(key) as T; break; } return res; }
代碼解析: 與上面的saveData()
函數相似, 一樣運用了泛型以及switch
. 不一樣的是讀取數據時調用的是prefs.getXXX()
代碼截圖:
到這裏, 咱們幾乎已經完成了咱們的教程. 反應快的同窗應該已經能夠直接使用了. 可是阿航的教程要保證其完整性, 讓你們都會用, 而且理解爲何這麼用. 咱們來繪製APP界面, 更直觀的測試!
回到./lib/main.dart
, 咱們來增長几個按鈕和輸入框.
SharedPreferencesUtil
先導入SharedPreferencesUtil
方便後續使用:
import 'package:my_shared_preferences_demo/shared_preferences_util.dart';
在_MyHomePageState
定義實例變量_savedValue
和_currentInputValue
, 用於記錄存儲及當前輸入的值:
// 保存的值 String _savedValue = "加載中.."; // 當前輸入的值 String _currentInputValue;
定義initState()
, 在初始化頁面時讀取已存的數據
@override void initState() { super.initState(); SharedPreferencesUtil.getData<String>("myData").then((value) { setState(() { _savedValue = value; }); }); }
代碼解析: 能夠看到initState()
上有@override
, 由於initState()
爲繼承過來的函數. 函數內部先調用super.initState()
. 接下來就是經過此前定義的SharedPreferencesUtil
獲取存儲的數據. 由於shared_preferences
提供的函數是async
(異步)的, 因此須要經過.then()
來保證其獲取到數據後再進行後續操做. 獲取到value後, 存至_savedValue.
接下來就是繪製界面了, 在build
->Scaffold
->body:Center
->child: Column
->children
中添加如下代碼塊:
// 用於顯示數據的Text Text( _savedValue == null ? "無數據" : _savedValue, style: TextStyle(fontSize: 60, fontWeight: FontWeight.bold), ), // 用於修改數據的輸入框 TextField( onChanged: (value) { _currentInputValue = value; }, // 僅爲美觀, 增長輸入框的邊框 decoration: InputDecoration( contentPadding: EdgeInsets.all(10.0), border: OutlineInputBorder( borderRadius: BorderRadius.circular(15.0), )), ), Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ // 用於觸發保存數據的按鈕 RaisedButton( child: Text("保存"), onPressed: () { // 當點擊按鈕時, 調用存儲數據的函數 SharedPreferencesUtil.saveData<String>( "myData", _currentInputValue); // 同時渲染當前顯示的保存的值 setState(() { _savedValue = _currentInputValue; }); }, ), RaisedButton( child: Text("清空數據"), onPressed: () { // 當點擊按鈕時, 調用存儲數據的函數 SharedPreferencesUtil.saveData<String>("myData", null); // 同時渲染當前顯示的保存的值 setState(() { _savedValue = "無數據"; }); }, ) ], ),
代碼解析: 這裏雖然看起來代碼多一點, 實質上只有1個輸入框和2個按鈕. 裏面沒有特別複雜的邏輯, 全部說明都在代碼註釋中, 可自行查看.
以上的代碼截圖:
若你的代碼沒有問題, 運行項目, 效果應該是這樣的:
經過以上的一些步驟, 咱們終於完成了 Flutter數據存儲之SharedPreference, 是否是很簡單?
全部源碼(含註釋)均已上傳至開源倉庫:
對文章如有任何問題、異議以及改進建議, 歡迎在下方進行評論. 做者將盡快回復! 若圖片展現異常, 歡迎閱讀官方博客.
更多更好的教程/博客/資訊, 歡迎訪問個人官網: 阿航的技術小站.