Flutter 中 shared_preferences 的使用
在移动应用开发中,我们经常需要将一些数据持久化保存,以便在应用重启或用户再次使用时能够恢复这些数据。shared_preferences 是 Flutter 提供的一个简单易用的库,专门用于在应用本地存储轻量级的键值对数据。
一. 简介
shared_preferences 是一个用于存储少量数据的轻量级插件,适用于保存简单的键值对数据,如布尔值、整数、字符串和字符串列表等。例如:保存应用的配置参数、用户偏好设置以及一些简单的状态数据。数据可能会异步持久化到磁盘,并且不能保证写入返回后会持久化到磁盘,因此该插件不得用于存储关键数据。
二. 安装shared_preferences
首先,我们需要将 shared_preferences 库添加到项目的 pubspec.yaml 文件中:
dependencies:
flutter:
sdk: flutter
shared_preferences: ^2.3.1
运行 flutter pub get 命令来安装依赖。
三. 基本用法
支持的数据类型为 int 、 double 、 bool 、 String 和 List 。
- 存储数据
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setInt('counter', 10);
prefs.setBool('repeat', true);
prefs.setDouble('decimal', 1.5);
prefs.setString('action', 'Start');
prefs.setStringList('items', <String>['Earth', 'Moon', 'Sun']);
- 读取数据
final int? counter = prefs.getInt('counter');
final bool? repeat = prefs.getBool('repeat');
final double? decimal = prefs.getDouble('decimal');
final String? action = prefs.getString('action');
final List<String>? items = prefs.getStringList('items');
例子:假设我们想要保存一个布尔值表示用户是否已登录:
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class MyHomePage extends StatefulWidget {
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _isLoggedIn = false;
void initState() {
super.initState();
_loadLoginStatus();
}
// 加载登录状态
_loadLoginStatus() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
_isLoggedIn = (prefs.getBool('isLoggedIn') ?? false);
});
}
// 保存登录状态
_saveLoginStatus(bool value) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool('isLoggedIn', value);
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("SharedPreferences Example"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
_isLoggedIn ? "Logged In" : "Logged Out",
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
setState(() {
_isLoggedIn = !_isLoggedIn;
_saveLoginStatus(_isLoggedIn);
});
},
child: Text(_isLoggedIn ? "Logout" : "Login"),
),
],
),
),
);
}
}
_loadLoginStatus() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
_isLoggedIn = (prefs.getBool('isLoggedIn') ?? false);
});
}
四. 清除数据
final SharedPreferences prefs = await SharedPreferences.getInstance();
// 清除特定数据
prefs.remove('counter');
// 清除所有数据
prefs.clear();
SharedPreferencesAsync 允许用户直接调用平台来获取设备上保存的最新偏好设置,但代价是异步,速度比使用缓存版本慢一点。这对于可以由其他系统或隔离区更新的偏好设置很有用,因为更新缓存会使缓存失效。
final SharedPreferencesAsync asyncPrefs = SharedPreferencesAsync();
await asyncPrefs.setBool('repeat', true);
await asyncPrefs.setString('action', 'Start');
final bool? repeat = await asyncPrefs.getBool('repeat');
final String? action = await asyncPrefs.getString('action');
await asyncPrefs.remove('repeat');
// Any time a filter option is included as a method parameter, strongly consider
// using it to avoid potentially unwanted side effects.
await asyncPrefs.clear(allowList: <String>{'action', 'repeat'});
SharedPreferencesWithCache 建立在 SharedPreferencesAsync 之上,允许用户同步访问本地缓存的偏好设置副本。这与旧 API 类似,但现在可以使用不同的参数多次实例化。
final SharedPreferencesWithCache prefsWithCache =
await SharedPreferencesWithCache.create(
cacheOptions: const SharedPreferencesWithCacheOptions(
// When an allowlist is included, any keys that aren't included cannot be used.
allowList: <String>{'repeat', 'action'},
),
);
await prefsWithCache.setBool('repeat', true);
await prefsWithCache.setString('action', 'Start');
final bool? repeat = prefsWithCache.getBool('repeat');
final String? action = prefsWithCache.getString('action');
await prefsWithCache.remove('repeat');
// Since the filter options are set at creation, they aren't needed during clear.
await prefsWithCache.clear();
五. 存储位置
平台 | SharedPreferences | SharedPreferencesAsync/WithCache |
---|---|---|
Android | SharedPreferences | DataStore Preferences 数据存储首选项 |
iOS | NSUserDefaults NS | NSUserDefaults NS |
macOS | NSUserDefaults NS | NSUserDefaults NS |
Linux | In the XDG_DATA_HOME directory | In the XDG_DATA_HOME directory |
Web | LocalStorage | LocalStorage |
Windows | AppData目录中 | AppData目录中 |
六. 优缺点
优点
- 简单易用:通过键值对的方式存储和读取数据,非常直观。
- 轻量级:适合存储少量的数据,如用户偏好设置、简单的配置信息等。相比于数据库,它的资源占用更少,性能较高。
- 跨平台支持: 支持 iOS、Android 和 Web 平台,可以在不同平台上使用相同的代码来进行数据持久化存储。
- 异步操作:存储和读取操作都是异步进行的,避免了主线程的阻塞,保证了应用的流畅性。
- 无外部依赖:不依赖于其他外部库或服务,只需将其添加到项目依赖中即可使用,使用起来非常方便。
缺点
- 数据量有限:适用于存储轻量级的数据,通常是少量的键值对。不适合存储大量数据或复杂的数据结构(如大型 JSON 对象、二进制文件等)。
- 性能限制:频繁读取或写入大量数据时,性能可能会受到影响。对于需要频繁进行数据操作的应用,可能需要考虑使用其他更高效的数据存储方案。
- 数据不加密:数据是明文保存的,这意味着敏感信息(如密码、令牌)不应该直接通过 shared_preferences 存储。
- 缺乏结构化数据支持:只支持基本数据类型(布尔值、整数、字符串等)和字符串列表的存储,不支持复杂的对象或嵌套结构的数据存储。如果需要存储更复杂的数据结构,必须手动序列化和反序列化,增加了代码复杂性。
- 数据同步性:在 Web 平台或多设备环境下,shared_preferences 不支持自动同步数据。如果用户在多个设备上使用应用,需要手动处理数据同步问题。
七. 总结
shared_preferences 适用于存储小量、非敏感的键值对数据。它的简单性和跨平台支持使其成为许多应用的首选方案,尤其是对于用户偏好设置、应用配置等场景。然而,对于需要处理大量数据、复杂数据结构或敏感信息的应用,shared_preferences 的局限性也不容忽视。