Flutter shared_preferences 的详细使用

在 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逻辑中处理它们,你可以使用 asyncawait 或者 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 方法中加载用户偏好的主题。

相关推荐
耳東陈1 小时前
Flutter开箱即用一站式解决方案-新增企业级日志
flutter
顾林海1 小时前
Flutter 图片组件全面解析:从基础加载到高级应用
android·前端·flutter
眼镜会飞1 小时前
Flutter window和Mac中webview2使用Cef替代
windows·flutter·mac
淡写成灰2 小时前
Flutter自定义带有Badger组件组
flutter
好的佩奇2 小时前
Dart 之任务
android·flutter·dart
豪冷啊16 小时前
Flutter Invalid constant value.
flutter
顾林海19 小时前
Flutter容器组件深度解析
android·前端·flutter
xq952719 小时前
mac os flutter 配置环境变量
flutter
sg_knight1 天前
Flutter性能优化终极指南:从JIT到AOT的深度调优
前端·flutter·性能优化·web·dart
zonda的地盘1 天前
[Get 源码] GetPageRoute 与 GetxController 的自动回收机制
flutter