如果你要存储的键值集合相对较少,则可以用 shared_preferences 插件。

通常你需要在两个平台用原生的方式存储数据。幸运的是 shared_preferences 插件可以把 key-value 保存到磁盘中。它通过封装 iOS 上的 NSUserDefaults 和 Android 上的 SharedPreferences 为简单数据提供持久化存储。

步骤

  • 添加依赖

  • 保存数据

  • 读取数据

  • 移除数据

1. 添加依赖

在开始之前,你需要在 pubspec.yaml 文件中添加 shared_preferences 插件:

  1. dependencies:
  2. flutter:
  3. sdk: flutter
  4. shared_preferences: "<newest version>"

2. 保存数据

要存储数据,请使用 SharedPreferences 类的 setter 方法。Setter方法可用于各种基本数据类型,例如 setIntsetBool, 和 setString

Setter 方法做两件事:首先,同步更新 key-value 到内存中,然后保存到磁盘中。

  1. // obtain shared preferences
  2. final prefs = await SharedPreferences.getInstance();
  3. // set value
  4. prefs.setInt('counter', counter);

3. 读取数据

要读取数据,请使用 SharedPreferences 类相应的 getter 方法。对于每一个 setter 方法都有对应的 getter 方法。例如,你可以使用 getIntgetBool,和 getString 方法。

  1. final prefs = await SharedPreferences.getInstance();
  2. // Try reading data from the counter key. If it does not exist, return 0.
  3. final counter = prefs.getInt('counter') ?? 0;

4. 移除数据

使用 remove 方法删除数据。

  1. final prefs = await SharedPreferences.getInstance();
  2. prefs.remove('counter');

支持类型

虽然使用 key-value 存储非常简单方便,但是它也有以下局限性:

  • 只能用于基本数据类型: intdoubleboolstringstringList

  • 不适用于大量数据的存储。

关于 Android 平台上 Shared Preferences 的更多信息,请前往 Android 开发者网站上查看 Shared preferences 文档

测试支持

使用 shared_preferences 存储数据来测试代码是一个不错的思路。为此,你需要模拟出 shared_preferences 库的 MethodChannel 方法。

在你的测试中,你可以通过在测试文件的 setupAll 方法中添加运行以下代码,对 SharedPreferences 的值进行初始:

  1. const MethodChannel('plugins.flutter.io/shared_preferences')
  2. .setMockMethodCallHandler((MethodCall methodCall) async {
  3. if (methodCall.method == 'getAll') {
  4. return <String, dynamic>{}; // set initial values here if desired
  5. }
  6. return null;
  7. });

示例

  1. import 'package:flutter/material.dart';
  2. import 'package:shared_preferences/shared_preferences.dart';
  3. void main() => runApp(MyApp());
  4. class MyApp extends StatelessWidget {
  5. // This widget is the root of the application.
  6. @override
  7. Widget build(BuildContext context) {
  8. return MaterialApp(
  9. title: 'Shared preferences demo',
  10. theme: ThemeData(
  11. primarySwatch: Colors.blue,
  12. ),
  13. home: MyHomePage(title: 'Shared preferences demo'),
  14. );
  15. }
  16. }
  17. class MyHomePage extends StatefulWidget {
  18. MyHomePage({Key key, this.title}) : super(key: key);
  19. final String title;
  20. @override
  21. _MyHomePageState createState() => _MyHomePageState();
  22. }
  23. class _MyHomePageState extends State<MyHomePage> {
  24. int _counter = 0;
  25. @override
  26. void initState() {
  27. super.initState();
  28. _loadCounter();
  29. }
  30. //Loading counter value on start
  31. _loadCounter() async {
  32. SharedPreferences prefs = await SharedPreferences.getInstance();
  33. setState(() {
  34. _counter = (prefs.getInt('counter') ?? 0);
  35. });
  36. }
  37. //Incrementing counter after click
  38. _incrementCounter() async {
  39. SharedPreferences prefs = await SharedPreferences.getInstance();
  40. setState(() {
  41. _counter = (prefs.getInt('counter') ?? 0) + 1;
  42. prefs.setInt('counter', _counter);
  43. });
  44. }
  45. @override
  46. Widget build(BuildContext context) {
  47. return Scaffold(
  48. appBar: AppBar(
  49. title: Text(widget.title),
  50. ),
  51. body: Center(
  52. child: Column(
  53. mainAxisAlignment: MainAxisAlignment.center,
  54. children: <Widget>[
  55. Text(
  56. 'You have pushed the button this many times:',
  57. ),
  58. Text(
  59. '$_counter',
  60. style: Theme.of(context).textTheme.display1,
  61. ),
  62. ],
  63. ),
  64. ),
  65. floatingActionButton: FloatingActionButton(
  66. onPressed: _incrementCounter,
  67. tooltip: 'Increment',
  68. child: Icon(Icons.add),
  69. ), // This trailing comma makes auto-formatting nicer for build methods.
  70. );
  71. }
  72. }