本地存储
本章将介绍 Flutter 中的数据持久化方案,包括 SharedPreferences、SQLite 等。
SharedPreferences
SharedPreferences 适合存储简单的键值对数据,如用户设置、登录状态等。
添加依赖
dependencies:
shared_preferences: ^2.0.0
基本用法
import 'package:shared_preferences/shared_preferences.dart';
class SharedPreferencesExample {
// 存储数据
static Future<void> saveData() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('username', '张三');
await prefs.setInt('age', 25);
await prefs.setBool('isLogin', true);
await prefs.setDouble('score', 95.5);
await prefs.setStringList('favorites', ['苹果', '香蕉', '橙子']);
}
// 读取数据
static Future<void> loadData() async {
final prefs = await SharedPreferences.getInstance();
final username = prefs.getString('username') ?? '未设置';
final age = prefs.getInt('age') ?? 0;
final isLogin = prefs.getBool('isLogin') ?? false;
final score = prefs.getDouble('score') ?? 0.0;
final favorites = prefs.getStringList('favorites') ?? [];
print('用户名:$username');
print('年龄:$age');
print('是否登录:$isLogin');
print('分数:$score');
print('收藏:$favorites');
}
// 删除数据
static Future<void> removeData() async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove('username');
}
// 清空所有数据
static Future<void> clearAll() async {
final prefs = await SharedPreferences.getInstance();
await prefs.clear();
}
// 检查是否存在
static Future<bool> containsKey(String key) async {
final prefs = await SharedPreferences.getInstance();
return prefs.containsKey(key);
}
}
封装工具类
class StorageService {
static late SharedPreferences _prefs;
static Future<void> init() async {
_prefs = await SharedPreferences.getInstance();
}
// String
static Future<bool> setString(String key, String value) =>
_prefs.setString(key, value);
static String getString(String key, [String defaultValue = '']) =>
_prefs.getString(key) ?? defaultValue;
// Int
static Future<bool> setInt(String key, int value) =>
_prefs.setInt(key, value);
static int getInt(String key, [int defaultValue = 0]) =>
_prefs.getInt(key) ?? defaultValue;
// Bool
static Future<bool> setBool(String key, bool value) =>
_prefs.setBool(key, value);
static bool getBool(String key, [bool defaultValue = false]) =>
_prefs.getBool(key) ?? defaultValue;
// Double
static Future<bool> setDouble(String key, double value) =>
_prefs.setDouble(key, value);
static double getDouble(String key, [double defaultValue = 0.0]) =>
_prefs.getDouble(key) ?? defaultValue;
// List<String>
static Future<bool> setStringList(String key, List<String> value) =>
_prefs.setStringList(key, value);
static List<String> getStringList(String key) =>
_prefs.getStringList(key) ?? [];
// Remove
static Future<bool> remove(String key) => _prefs.remove(key);
// Clear
static Future<bool> clear() => _prefs.clear();
// Contains
static bool containsKey(String key) => _prefs.containsKey(key);
}
// 在 main 中初始化
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await StorageService.init();
runApp(MyApp());
}
SQLite
SQLite 适合存储结构化数据,支持复杂的查询操作。
添加依赖
dependencies:
sqflite: ^2.0.0
path: ^1.8.0
基本用法
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
class DatabaseHelper {
static Database? _database;
static Future<Database> get database async {
if (_database != null) return _database!;
_database = await _initDatabase();
return _database!;
}
static Future<Database> _initDatabase() async {
final dbPath = await getDatabasesPath();
final path = join(dbPath, 'app.db');
return openDatabase(
path,
version: 1,
onCreate: (db, version) async {
await db.execute('''
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT NOT NULL,
age INTEGER
)
''');
},
);
}
// 插入数据
static Future<int> insertUser(Map<String, dynamic> user) async {
final db = await database;
return await db.insert('users', user);
}
// 查询所有
static Future<List<Map<String, dynamic>>> getUsers() async {
final db = await database;
return await db.query('users');
}
// 条件查询
static Future<List<Map<String, dynamic>>> getUserById(int id) async {
final db = await database;
return await db.query('users', where: 'id = ?', whereArgs: [id]);
}
// 更新数据
static Future<int> updateUser(int id, Map<String, dynamic> user) async {
final db = await database;
return await db.update('users', user, where: 'id = ?', whereArgs: [id]);
}
// 删除数据
static Future<int> deleteUser(int id) async {
final db = await database;
return await db.delete('users', where: 'id = ?', whereArgs: [id]);
}
// 原生 SQL
static Future<List<Map<String, dynamic>>> rawQuery(String sql) async {
final db = await database;
return await db.rawQuery(sql);
}
}
使用示例
class UserDatabasePage extends StatefulWidget {
@override
_UserDatabasePageState createState() => _UserDatabasePageState();
}
class _UserDatabasePageState extends State<UserDatabasePage> {
List<Map<String, dynamic>> _users = [];
@override
void initState() {
super.initState();
_loadUsers();
}
Future<void> _loadUsers() async {
final users = await DatabaseHelper.getUsers();
setState(() => _users = users);
}
Future<void> _addUser() async {
await DatabaseHelper.insertUser({
'name': '用户${_users.length + 1}',
'email': 'user${_users.length + 1}@example.com',
'age': 20 + _users.length,
});
_loadUsers();
}
Future<void> _deleteUser(int id) async {
await DatabaseHelper.deleteUser(id);
_loadUsers();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('数据库示例')),
body: ListView.builder(
itemCount: _users.length,
itemBuilder: (context, index) {
final user = _users[index];
return ListTile(
title: Text(user['name']),
subtitle: Text(user['email']),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => _deleteUser(user['id']),
),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: _addUser,
child: Icon(Icons.add),
),
);
}
}
事务
static Future<void> batchInsert(List<Map<String, dynamic>> users) async {
final db = await database;
await db.transaction((txn) async {
for (var user in users) {
await txn.insert('users', user);
}
});
}
文件存储
适合存储较大的数据或文件。
添加依赖
dependencies:
path_provider: ^2.0.0
读写文件
import 'dart:io';
import 'package:path_provider/path_provider.dart';
class FileStorage {
// 获取应用文档目录
static Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
// 获取文件
static Future<File> _localFile(String filename) async {
final path = await _localPath;
return File('$path/$filename');
}
// 写入文件
static Future<File> writeFile(String filename, String content) async {
final file = await _localFile(filename);
return file.writeAsString(content);
}
// 读取文件
static Future<String> readFile(String filename) async {
try {
final file = await _localFile(filename);
return await file.readAsString();
} catch (e) {
return '';
}
}
// 删除文件
static Future<void> deleteFile(String filename) async {
final file = await _localFile(filename);
if (await file.exists()) {
await file.delete();
}
}
// 检查文件是否存在
static Future<bool> fileExists(String filename) async {
final file = await _localFile(filename);
return file.exists();
}
}
加密存储
使用 flutter_secure_storage 存储敏感数据。
添加依赖
dependencies:
flutter_secure_storage: ^9.0.0
使用示例
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class SecureStorageService {
static final _storage = FlutterSecureStorage();
// 写入
static Future<void> write(String key, String value) async {
await _storage.write(key: key, value: value);
}
// 读取
static Future<String?> read(String key) async {
return await _storage.read(key: key);
}
// 删除
static Future<void> delete(String key) async {
await _storage.delete(key: key);
}
// 删除所有
static Future<void> deleteAll() async {
await _storage.deleteAll();
}
// 检查是否存在
static Future<bool> containsKey(String key) async {
return await _storage.containsKey(key: key);
}
}
// 使用场景:存储 Token
class AuthService {
static const _tokenKey = 'auth_token';
static Future<void> saveToken(String token) async {
await SecureStorageService.write(_tokenKey, token);
}
static Future<String?> getToken() async {
return await SecureStorageService.read(_tokenKey);
}
static Future<void> clearToken() async {
await SecureStorageService.delete(_tokenKey);
}
}
小结
本章我们学习了:
- SharedPreferences:简单的键值对存储
- SQLite:结构化数据存储和查询
- 文件存储:大文件的读写
- 加密存储:敏感数据的安全存储
练习
- 使用 SharedPreferences 实现应用设置功能
- 使用 SQLite 实现一个简单的笔记应用
- 实现离线缓存功能
- 使用加密存储实现登录 Token 管理