Flutter data storage --shared_preferences usage details

1. Shared_preferences Introduction

shared_preferencesThe main function is to asynchronously persist data to the disk , because the persistent data is only stored in a temporary directory. When the app is deleted, the stored data will disappear, and the data stored in the browser will also disappear during web development.

Supported storage types:

  • bool
  • int
  • double
  • string
  • stringList

shared_preferences application scenario

Mainly used for persistent data, such as persistent user information, list data, etc.

Persistent user information

Because user information basically does not change, and there are often multiple pages in an application that need to display user information, it is impossible for us to obtain the interface every time, so local persistence will become very convenient.

persistent list data

In order to give users a better experience, we often display the old data first when obtaining list data, so as to bring users a better experience, so that the page will not be blank as soon as we open it. Display the local data, and update the data when the network data request comes back.

The corresponding class library used by shared_preferences

We know that each platform has a different way of persisting data, and shared_preferencesa common class library is encapsulated for different platforms. Next, let's look at the libraries they use under different platforms:

  • iOS: NSUserDefaults
  • Android: SharedPreferences
  • Web: localStorage
  • Linux:  FileSystem (save data to the local system file library)
  • Mac OS:  FileSystem (save data to the local system file library)
  • Windows:  FileSystem (save data to the local system file library)

2. shared_preferences basic use

import header file

import 'package:shared_preferences/shared_preferences.dart';

Get instance object

SharedPreferences? sharedPreferences = await SharedPreferences.getInstance();

2.1. Storage and reading of persistent data

We can sharedPreferencescall the corresponding setmethod to set the persistent data through the instantiated object, and obtain it through the get method.

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class SharedPreferencesExample extends StatefulWidget {
  @override
  _SharedPreferencesExampleState createState() => _SharedPreferencesExampleState();
}

class _SharedPreferencesExampleState extends State<SharedPreferencesExample> {


  SharedPreferences? sharedPreferences;

  // 设置持久化数据
  void _setData() async {
    // 实例化
    sharedPreferences = await SharedPreferences.getInstance();

    // 设置string类型
    await sharedPreferences?.setString("name", "Jimi");

    // 设置int类型
    await sharedPreferences?.setInt("age", 18);

    // 设置bool类型
    await sharedPreferences?.setBool("isTeacher", true);

    // 设置double类型
    await sharedPreferences?.setDouble("height", 1.88);

    // 设置string类型的数组
    await sharedPreferences?.setStringList("action", ["吃饭", "睡觉", "打豆豆"]);

    setState(() {});
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("SharedPreferences"),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _setData,
        child: Icon(Icons.add),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Text("名字: ${sharedPreferences?.getString("name") ?? ""}",
                 style: TextStyle(
                   color: Colors.blue,
                   fontSize: 20
                 ),
                ),
            SizedBox(height: 20,),
            Text("年龄: ${sharedPreferences?.getInt("age") ?? ""}",
                 style: TextStyle(
                   color: Colors.red,
                   fontSize: 20
                 ),
                ),
            SizedBox(height: 20,),
            Text("是老师吗?: ${sharedPreferences?.getBool("isTeacher") ?? ""}",
                 style: TextStyle(
                   color: Colors.orange,
                   fontSize: 20
                 ),
                ),
            SizedBox(height: 20,),
            Text("身高: ${sharedPreferences?.getDouble("height") ?? ""}",
                 style: TextStyle(
                   color: Colors.pink,
                   fontSize: 20
                 ),
                ),
            SizedBox(height: 20,),
            Text("我正在: ${sharedPreferences?.getStringList("action") ?? ""}",
                 style: TextStyle(
                   color: Colors.purple,
                   fontSize: 20
                 ),
                ),
          ],
        ),
      ),
    );
  }
}

  2.2. Obtain all stored keys in the persistent data

List<String> keys = sharedPreferences?.getKeys().toList() ?? [];
print(keys);

// 控制台输出
[name, age, isTeacher, height, action]

2.3. Determine whether a key is contained in the persistent data

bool isContainKey = sharedPreferences?.containsKey("name") ?? false;
print(isContainKey);

// 控制台输出
flutter: true

2.4. Delete a key in the persistent data

bool isRemoveKey = await sharedPreferences?.remove("name") ?? false;
print(isRemoveKey);

// 控制台输出
flutter: true

2.5. Clear all persistent data

bool isClearAllKey = await sharedPreferences?.clear() ?? false;
print(isClearAllKey);

// 控制台输出
flutter: true

2.6. Reload all data (reload runtime only)

await sharedPreferences?.reload();

3. shared_preferences encapsulation

We shared_preferencesneed to obtain its instance every time we use it. If it is used in multiple places, it must be instantiated every time. The readability of the code is poor, the later maintenance cost becomes very high, and the storage Maptype is not supported, so next we will shared_preferencesencapsulate a general-purpose and easier-to-use library.

Shared_preferences encapsulation using singleton mode

Because we get the same instance, it is best to use the singleton mode for encapsulation, and the instance is asynchronous, so we initialize it when the application starts, which is more convenient to use.

Create a singleton class

Because our code uses empty security, there is a very important attribute in empty security lateto delay loading our instances, as follows.

class JSpUtil {

  JSpUtil._internal();
  
  factory JSpUtil() => _instance;

  static late final JSpUtil _instance = JSpUtil._internal();
}

Initialize shared_preferences

Because the singleton mode is adopted, when obtaining the only instance, we can obtain it once at the entrance.

static late SharedPreferences _preferences;

static Future<JSpUtil> getInstance() async {
  _preferences = await SharedPreferences.getInstance();
  return _instance;
}

Encapsulation method 1: corresponding to get and set methods

/// 根据key存储int类型
static Future<bool> setInt(String key, int value) {
  return _preferences.setInt(key, value);
}

/// 根据key获取int类型
static int? getInt(String key, {int defaultValue = 0}) {
  return _preferences.getInt(key) ?? defaultValue;
}

/// 根据key存储double类型
static Future<bool> setDouble(String key, double value) {
  return _preferences.setDouble(key, value);
}

/// 根据key获取double类型
static double? getDouble(String key, {double defaultValue = 0.0}) {
  return _preferences.getDouble(key) ?? defaultValue;
}

/// 根据key存储字符串类型
static Future<bool> setString(String key, String value) {
  return _preferences.setString(key, value);
}

/// 根据key获取字符串类型
static String? getString(String key, {String defaultValue = ""}) {
  return _preferences.getString(key) ?? defaultValue;
}

/// 根据key存储布尔类型
static Future<bool> setBool(String key, bool value) {
  return _preferences.setBool(key, value);
}

/// 根据key获取布尔类型
static bool? getBool(String key, {bool defaultValue = false}) {
  return _preferences.getBool(key) ?? defaultValue;
}

/// 根据key存储字符串类型数组
static Future<bool> setStringList(String key, List<String> value) {
  return _preferences.setStringList(key, value);
}

/// 根据key获取字符串类型数组
static List<String> getStringList(String key, {List<String> defaultValue = const []}) {
  return _preferences.getStringList(key) ?? defaultValue;
}

/// 根据key存储Map类型
static Future<bool> setMap(String key, Map value) {
  return _preferences.setString(key, json.encode(value));
}

/// 根据key获取Map类型
static Map getMap(String key) {
  String jsonStr = _preferences.getString(key) ?? "";
  return jsonStr.isEmpty ? Map : json.decode(jsonStr);
}

Encapsulation method 2: unified set and get methods

/// 通用设置持久化数据
static setLocalStorage<T>(String key, T value) {
  String type = value.runtimeType.toString();

  switch (type) {
    case "String":
      setString(key, value as String);
      break;
    case "int":
      setInt(key, value as int);
      break;
    case "bool":
      setBool(key, value as bool);
      break;
    case "double":
      setDouble(key, value as double);
      break;
    case "List<String>":
      setStringList(key, value as List<String>);
      break;
    case "_InternalLinkedHashMap<String, String>":
      setMap(key, value as Map);
      break;
  }
}

/// 获取持久化数据
static dynamic getLocalStorage<T>(String key) {
  dynamic value = _preferences.get(key);
  if (value.runtimeType.toString() == "String") {
    if (_isJson(value)) {
      return json.decode(value);
    }
  }
  return value;
}

The use of two packages

// 设置String类型
await JSpUtil.setString("name", "Jimi");

// 设置int类型
await JSpUtil.setInt("age", 18);

// 设置bool类型
await JSpUtil.setBool("isTeacher", true);

// 设置double类型
await JSpUtil.setDouble("height", 1.88);

// 设置string类型的数组
await JSpUtil.setStringList("action", ["吃饭", "睡觉", "打豆豆"]);

// 设置Map类型
await JSpUtil.setMap("weight", {"weight": 112});

JSpUtil.setLocalStorage("name", "Jimi");
JSpUtil.setLocalStorage("age", 18);
JSpUtil.setLocalStorage("isTeacher", true);
JSpUtil.setLocalStorage("height", 1.88);
JSpUtil.setLocalStorage("action", ["吃饭", "睡觉", "打豆豆"]);
JSpUtil.setLocalStorage("weight", {"weight": "112"});

JSpUtil.getLocalStorage("name");
JSpUtil.getLocalStorage("age");
JSpUtil.getLocalStorage("isTeacher");
JSpUtil.getLocalStorage("height");
JSpUtil.getLocalStorage("action");
JSpUtil.getLocalStorage("weight");


// 获取磁盘中所有存入的key
List<String> keys = JSpUtil.getKeys().toList();
print(keys);

// 持久化数据中是否包含某个key
bool isContainKey = JSpUtil.containsKey("name");
print(isContainKey);

// 删除持久化数据中某个key
bool isRemoveKey = await JSpUtil.remove("name");
print(isRemoveKey);

// 清除所有持久化数据
bool isClearAllKey = await JSpUtil.clear();
print(isClearAllKey);

// 重新加载所有数据,仅重载运行时
await JSpUtil.reload();

way to get the value

Text("名字: ${JSpUtil.getString("name")}",
     style: TextStyle(
       color: Colors.blue,
       fontSize: 20
     ),
    ),
SizedBox(height: 20,),
Text("年龄: ${JSpUtil.getInt("age")}",
     style: TextStyle(
       color: Colors.red,
       fontSize: 20
     ),
    ),
SizedBox(height: 20,),
Text("是老师吗?: ${JSpUtil.getBool("isTeacher")}",
     style: TextStyle(
       color: Colors.orange,
       fontSize: 20
     ),
    ),
SizedBox(height: 20,),
Text("身高: ${JSpUtil.getDouble("height")}",
     style: TextStyle(
       color: Colors.pink,
       fontSize: 20
     ),
    ),
SizedBox(height: 20,),
Text("我正在: ${JSpUtil.getStringList("action")}",
     style: TextStyle(
       color: Colors.purple,
       fontSize: 20
     ),
    ),

Guess you like

Origin blog.csdn.net/eastWind1101/article/details/127977741