likes
comments
collection
share

Flutter shared_preferences 的详细使用

作者站长头像
站长
· 阅读数 10

在 Flutter 中,shared_preferences 是一个轻量级的持久化存储插件,用于存储简单的数据类型。它提供了一个 key-value 存储机制,可以用来存储整型、浮点型、字符串和布尔型等数据。

记得在使用 shared_preferences 的时候,理解其背后的原理。当你调用 set 方法时,如 setString 或者 setBool,这些数据实际上是在内存中被缓存了一份,然后异步地写入到磁盘中。因此调用 set 方法非常快,因为它不会立即进行磁盘的读写操作。

存储数据

要存储数据,你需要获取 SharedPreferences 实例然后使用它来保存你想要的数据:

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']);

读取数据

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') ?? [];

删除数据

final prefs = await SharedPreferences.getInstance();

// 删除特定的键
prefs.remove('username');

// 清除所有键
prefs.clear();

注意事项

  • shared_preferences插件会在后台执行异步操作,所以你不需要担心它会影响应用的UI性能。当操作返回的是 Future 时,你需要确保在UI逻辑中处理它们,你可以使用 async 和 await 或者 then 方法。

例:使用 FutureBuilder

你可以在 UI 中直接展示 SharedPreferences 的数据,通过使用 FutureBuilder

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 应用中非常实用。

异步操作的效果

对于存储的操作,比如:

await prefs.setString('username', 'FlutterDev');

虽然使用了 await,但这不意味着数据已经被写入到文件中。写入操作将在后台进行,而在操作完成之前,await 将会等待的是将数据写入内存的操作。

异步数据获取

获取数据的时候通常要这么做:

String? username = await prefs.getString('username');

这里的 await 确保的是如果数据还没有被存入内存,那么它将会等待读磁盘的操作。

数据一致性

因为 shared_preferences 是异步的,所以在并发写入时可能会有数据一致性的问题。当多个异步写入操作同时触发时,SharedPreferences 实际上只会执行最后的写入操作,前面的写入可能会被覆盖。因此,如果你的应用场景涉及到复杂的数据写入逻辑,那么应该仔细设计你的数据存储方案,或者使用其他更适合的存储方式。

示例

最后,给出一个简单的使用 shared_preferences 来存储和获取数据,以及以及当在 Flutter 应用中缓存用户偏好设置的例子:

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 方法中加载用户偏好的主题。

转载自:https://juejin.cn/post/7342793254096125967
评论
请登录