存储键值对数据
如果你要存储的键值集合相对较少,则可以用 shared_preferences
插件。
If you have a relatively small collection of key-values
to save, you can use the shared_preferences
plugin.
通常你需要在两个平台用原生的方式存储数据。幸运的是 shared_preferences
插件可以把 key-value 保存到磁盘中。它通过封装 iOS 上的 NSUserDefaults
和 Android
上的 SharedPreferences
为简单数据提供持久化存储。
Normally,
you would have to write native platform integrations for storing
data on both iOS and Android. Fortunately,
the shared_preferences
plugin can be used to persist
key-value data on disk. The shared preferences plugin
wraps NSUserDefaults
on iOS and SharedPreferences
on Android,
providing a persistent store for simple data.
这个教程包含以下步骤:
This recipe uses the following steps:
-
添加依赖
Add the dependency.
-
保存数据
Save Data.
-
读取数据
Read Data.
-
移除数据
Remove Data.
1. 添加依赖
1. Add the dependency
在开始之前,你需要在 pubspec.yaml
文件中添加 shared_preferences
插件:
Before starting, add the shared_preferences
plugin to the pubspec.yaml
file:
dependencies:
flutter:
sdk: flutter
shared_preferences: "<newest version>"
2. 保存数据
2. Save data
要存储数据,请使用 SharedPreferences
类的 setter 方法。
Setter方法可用于各种基本数据类型,例如 setInt
、setBool
和 setString
。
To persist data, use the setter methods provided by the
SharedPreferences
class. Setter methods are available for
various primitive types, such as setInt
, setBool
, and setString
.
Setter 方法做两件事:首先,同步更新 key-value 到内存中,然后保存到磁盘中。
Setter methods do two things: First, synchronously update the key-value pair in-memory. Then, persist the data to disk.
// obtain shared preferences final prefs = await SharedPreferences.getInstance(); // set value prefs.setInt('counter', counter);
3. 读取数据
3. Read data
要读取数据,请使用 SharedPreferences
类相应的 getter 方法。对于每一个 setter 方法都有对应的 getter 方法。例如,你可以使用 getInt
、getBool
和 getString
方法。
To read data, use the appropriate getter method provided by the
SharedPreferences
class. For each setter there is a corresponding getter.
For example, you can use the getInt
, getBool
, and getString
methods.
final prefs = await SharedPreferences.getInstance(); // Try reading data from the counter key. If it doesn't exist, return 0. final counter = prefs.getInt('counter') ?? 0;
4. 移除数据
4. Remove data
使用 remove()
方法删除数据。
To delete data, use the remove()
method.
final prefs = await SharedPreferences.getInstance(); prefs.remove('counter');
支持类型
Supported types
虽然使用 key-value 存储非常简单方便,但是它也有以下局限性:
Although key-value storage is easy and convenient to use, it has limitations:
-
只能用于基本数据类型:
int
、double
、bool
、string
和stringList
。Only primitive types can be used:
int
,double
,bool
,string
, andstringList
. -
不适用于大量数据的存储。
It’s not designed to store a lot of data.
关于 Android 平台上 Shared Preferences 的更多信息,请前往 Android 开发者网站上查看 Shared preferences 文档 。
For more information about shared preferences on Android, see the shared preferences documentation on the Android developers website.
测试支持
Testing support
使用 shared_preferences
存储数据来测试代码是一个不错的思路。为此,你需要模拟出 shared_preferences
库的 MethodChannel
方法。
It’s a good idea to test code that persists data using
shared_preferences
. You can do this by mocking out the
MethodChannel
used by the shared_preferences
library.
在你的测试中,你可以通过在测试文件的 setupAll()
方法中添加运行以下代码,对 SharedPreferences
的值进行初始:
Populate SharedPreferences
with initial values in your tests
by running the following code in a setupAll()
method in
your test files:
const MethodChannel('plugins.flutter.io/shared_preferences') .setMockMethodCallHandler((MethodCall methodCall) async { if (methodCall.method == 'getAll') { return <String, dynamic>{}; // set initial values here if desired } return null; });
完整示例
Complete example
import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); // This widget is the root of the application. @override Widget build(BuildContext context) { return const MaterialApp( title: 'Shared preferences demo', home: MyHomePage(title: 'Shared preferences demo'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int _counter = 0; @override void initState() { super.initState(); _loadCounter(); } //Loading counter value on start void _loadCounter() async { final prefs = await SharedPreferences.getInstance(); setState(() { _counter = (prefs.getInt('counter') ?? 0); }); } //Incrementing counter after click void _incrementCounter() async { final prefs = await SharedPreferences.getInstance(); setState(() { _counter = (prefs.getInt('counter') ?? 0) + 1; prefs.setInt('counter', _counter); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( 'You have pushed the button this many times:', ), Text( '$_counter', style: Theme.of(context).textTheme.headline4, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: const Icon(Icons.add), ), // This trailing comma makes auto-formatting nicer for build methods. ); } }