在 Flutter 中,shared_preferences
是一个轻量级的持久化存储插件,用于存储简单的数据类型。它提供了一个 key-value 存储机制,可以用来存储整型、浮点型、字符串和布尔型等数据。
存储数据
要存储数据,你需要获取 SharedPreferences
实例然后使用它来保存你想要的数据:
dart
final prefs = await SharedPreferences.getInstance();
// 存储字符串
prefs.setString('username', 'FlutterDev');
// 存储整型
prefs.setInt('counter', 10);
// 存储浮点型
prefs.setDouble('volume', 0.7);
// 存储布尔型
prefs.setBool('isUserLoggedIn', true);
// 存储字符串列表
prefs.setStringList('userRoles', ['admin', 'user']);
读取数据
dart
final prefs = await SharedPreferences.getInstance();
// 读取字符串,没有则返回 null
String? username = prefs.getString('username');
// 读取整型,没有则返回 0
int counter = prefs.getInt('counter') ?? 0;
// 读取浮点型,没有则返回 0.0
double volume = prefs.getDouble('volume') ?? 0.0;
// 读取布尔型,没有则返回 false
bool isUserLoggedIn = prefs.getBool('isUserLoggedIn') ?? false;
// 读取字符串列表,没有则返回空列表
List<String> userRoles = prefs.getStringList('userRoles') ?? [];
删除数据
dart
final prefs = await SharedPreferences.getInstance();
// 删除特定的键
prefs.remove('username');
// 清除所有键
prefs.clear();
注意事项
shared_preferences
插件会在后台执行异步操作,所以你不需要担心它会影响应用的UI性能。当操作返回的是Future
时,你需要确保在UI逻辑中处理它们,你可以使用async
和await
或者then
方法。
例:使用 FutureBuilder
你可以在 UI 中直接展示 SharedPreferences
的数据,通过使用 FutureBuilder
:
dart
FutureBuilder<SharedPreferences>(
future: SharedPreferences.getInstance(),
builder: (BuildContext context, AsyncSnapshot<SharedPreferences> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (!snapshot.hasError) {
final prefs = snapshot.data;
String? username = prefs?.getString('username') ?? "N/A";
// 使用数据来构建我们的UI
return Text('用户名: $username');
} else {
// 处理错误
return Text('发生错误');
}
} else {
// 数据还在加载中时显示加载指示器
return CircularProgressIndicator();
}
},
);
使用 FutureBuilder
的好处是你不需要管理 await 的状态,Flutter 会为你处理好。
作用域问题
确保在使用 SharedPreferences
的时候处理好作用域,如果需要在多个页面间共享同样的 SharedPreferences
的实例,可以在应用启动时获取该实例,然后将它传递到需要的地方。
性能考量
对于 shared_preferences
,因为它是轻量级的数据存储方案,不应该用它来存储大量数据。如果你确实需要存储大量数据,应该考虑使用数据库或者文件存储。
本地数据同步
SharedPreferences
并不是为了同步不同设备和用户之间的数据而设计的。如果你需要同步数据,可能需要考虑网络请求或者其他的同步机制。
总的来说,shared_preferences
是一个简单而高效的方法来在本地存储少量数据,在 Flutter 应用中非常实用。
记得在使用 shared_preferences
的时候,理解其背后的原理。当你调用 set
方法时,如 setString
或者 setBool
,这些数据实际上是在内存中被缓存了一份,然后异步地写入到磁盘中。因此调用 set
方法非常快,因为它不会立即进行磁盘的读写操作。
异步操作的效果
对于存储的操作,比如:
Dart
await prefs.setString('username', 'FlutterDev');
虽然使用了 await
,但这不意味着数据已经被写入到文件中。写入操作将在后台进行,而在操作完成之前,await
将会等待的是将数据写入内存的操作。
异步数据获取
获取数据的时候通常要这么做:
Dart
String? username = await prefs.getString('username');
这里的 await
确保的是如果数据还没有被存入内存,那么它将会等待读磁盘的操作。
数据一致性
因为 shared_preferences
是异步的,所以在并发写入时可能会有数据一致性的问题。当多个异步写入操作同时触发时,SharedPreferences
实际上只会执行最后的写入操作,前面的写入可能会被覆盖。因此,如果你的应用场景涉及到复杂的数据写入逻辑,那么应该仔细设计你的数据存储方案,或者使用其他更适合的存储方式。
示例
最后,给出一个简单的使用 shared_preferences
来存储和获取数据,以及以及当在 Flutter 应用中缓存用户偏好设置的例子:
dart
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Shared Preferences Demo',
home: SharedPreferencesDemo(),
);
}
}
class SharedPreferencesDemo extends StatefulWidget {
@override
_SharedPreferencesDemoState createState() => _SharedPreferencesDemoState();
}
class _SharedPreferencesDemoState extends State<SharedPreferencesDemo> {
late bool _isDarkTheme;
@override
void initState() {
super.initState();
_loadUserTheme();
}
// 加载用户偏好的主题
Future<void> _loadUserTheme() async {
final prefs = await SharedPreferences.getInstance();
setState(() {
_isDarkTheme = prefs.getBool('isDarkTheme') ?? false;
});
}
// 更新用户偏好的主题
Future<void> _updateUserTheme(bool isDarkTheme) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('isDarkTheme', isDarkTheme);
setState(() {
_isDarkTheme = isDarkTheme;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Shared Preferences Demo'),
),
body: Center(
child: SwitchListTile(
title: Text('暗黑模式'),
value: _isDarkTheme,
onChanged: (value) {
_updateUserTheme(value);
},
),
),
);
}
}
在这个简单的例子里,我们创建了一个 SwitchListTile
开关来控制主题偏好。当用户切换这个开关时,它更新 _isDarkTheme
状态并将用户的选择持久化保存到 shared_preferences
中。当应用启动时,它会在 initState
方法中加载用户偏好的主题。