Flutter 數據存儲 SharedPreferences

Flutter 數據存儲之SharedPreferences

我們在做APP開發時, 經常會涉及到用戶數據的存儲(比如保存用戶登錄token、用戶的某些偏好設置等). 開發過Android的朋友應該知道有 SharedPreferences. 在 Flutter 中, 同樣爲我們提供了十分相似的(甚至名字都一樣)組件, 爲我們提供數據存儲的能力.

本篇教程將用一個簡單的小Demo, 讓你完全掌握 數據存儲之SharedPreferences 的用法.

若圖片展示異常, 請訪問我的官方博客

效果

有圖有真相, 我們先來看一下我們最終的效果:

SharedPreferences最終效果

倉庫地址

所有源碼(含註釋)均已上傳至開源倉庫:

準備工作

開發環境

本博客的環境一覽:

環境 版本號
Flutter 1.14.6 beta
Dart 2.8.0-dev.5.0
Android Studio 3.5.2

注意您的環境和文中的差異, 避免出現不兼容的情況哦!

需具備的條件

要順利閱讀本文, 假定您已經具備以下條件:

  1. 一臺電腦(能同時運行IDE、APP模擬器).
  2. Android StudioVSCode(或任何你喜歡的代碼編輯器).
  3. Flutter開發環境.
  4. 您掌握了Flutter的開發基礎(至少了解目錄結構、Dart語言基本知識).

實戰開始

創建Flutter項目

創建一個新的Flutter項目, 命名爲my_shared_preferences_demo(您可以隨意起名, 但是在下面也要替換名字爲您自己的).

注意: Flutter項目名不要和引入的某個第三方庫重名, 否則會報: A package may not list itself as a dependency

代碼截圖:
初始化項目

清理代碼

因爲我們的項目過於簡單, 暫時不需要進行測試. 刪除./test目錄:

清理test目錄

避免冗餘代碼誤導我們, 替換./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>[],
        ),
      ),
    );
  }
}

導入 SharedPreferences 第三方庫

進入./pubspec.yaml, 添加依賴:

dependencies:
  shared_preferences: ^0.5.6+3

你也可以去官網查看最新的shared_preferences

截圖:
導入SharedPreferences庫

更新包, 在終端中輸入(或者點擊IDE的更新包的按鈕):

flutter packages get

運行項目:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MPOtBtmo-1586420827340)(https://i.loli.net/2020/04/09/JW1ToSuIQaFhUn9.png)]

現在, 我們可以正式進行數據存儲的操作了!

創建數據讀寫工具類

實際項目中, 我們定會多次用到數據的讀寫, 所以封裝一個工具類是比較明智的選擇.

創建./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), 完成數據存儲.

代碼截圖:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-v3zLnqVP-1586420827341)(https://i.loli.net/2020/04/09/nhY1DtTeLOwN8E3.png)]

數據讀取函數 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()

代碼截圖:

SharedPreferencesUtil02

到這裏, 我們幾乎已經完成了我們的教程. 反應快的同學應該已經可以直接使用了. 但是阿航的教程要保證其完整性, 讓大家都會用, 並且理解爲什麼這麼用. 我們來繪製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個按鈕. 裏面沒有特別複雜的邏輯, 所有說明都在代碼註釋中, 可自行查看.

以上的代碼截圖:

大功告成

若你的代碼沒有問題, 運行項目, 效果應該是這樣的:
SharedPreferences最終效果

通過以上的一些步驟, 我們終於完成了 Flutter數據存儲之SharedPreference, 是不是很簡單?

倉庫地址

所有源碼(含註釋)均已上傳至開源倉庫:

對文章若有任何問題、異議以及改進建議, 歡迎在下方進行評論. 作者將盡快回復! 若圖片展示異常, 歡迎閱讀官方博客.

更多更好的教程/博客/資訊, 歡迎訪問我的官網: 阿航的技術小站.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章