技术选型
- 数据库:
- SQLite:适用于Flutter本地数据存储,轻量级且在移动设备上性能较好。它支持事务,能保证数据一致性。可使用
sqflite
插件,能方便地进行数据的增删改查操作。例如,对于用户设置、应用配置等需要持久化的关键数据,可存储在SQLite数据库中。
- Hive:也是本地存储方案,基于文件系统,提供简单且高效的键值对存储。它具有较快的读写速度,适合存储一些频繁访问但结构相对简单的数据,如最近浏览记录等。通过
hive
插件实现,其开箱即用的特性方便快速集成。
- 缓存机制:
- In - memory缓存:在Flutter应用中,可使用
Map
来实现简单的内存缓存。对于经常使用且数据量不大的数据,在内存中缓存能快速访问,提升性能。例如,一些应用内频繁展示的配置信息,在应用启动时加载到内存缓存中,避免重复从数据库读取。
- Disk缓存:对于较大且不经常变化的数据,如图片、视频等资源,可使用
flutter_cache_manager
进行磁盘缓存。它能自动管理缓存的生命周期,根据策略清理过期缓存,节省磁盘空间。
不同类型状态数据的处理方式
- UI相关状态:
- 例如按钮的按下状态、列表的展开/折叠状态等,这类状态通常只影响UI展示,不涉及业务逻辑的核心数据。使用
ValueNotifier
或 ChangeNotifier
管理。在应用关闭或进入后台时,这些状态无需持久化,因为重新打开应用时,UI应恢复到初始默认状态。
- 示例:
class ButtonState extends ChangeNotifier {
bool _isPressed = false;
bool get isPressed => _isPressed;
void togglePress() {
_isPressed =!_isPressed;
notifyListeners();
}
}
- 业务逻辑状态:
- 如用户登录状态、购物车中的商品列表等,这些数据对业务流程至关重要。使用
Provider
或 Riverpod
等状态管理库结合数据库存储。当状态发生变化时,同时更新数据库。例如,用户登录成功后,将登录状态和用户信息存储到SQLite数据库,并通过状态管理库通知UI更新。
- 示例(使用Provider):
class UserModel {
String? name;
bool isLoggedIn = false;
}
class UserProvider with ChangeNotifier {
UserModel _user = UserModel();
UserModel get user => _user;
void login(String name) {
_user.name = name;
_user.isLoggedIn = true;
// 同时更新数据库
//...
notifyListeners();
}
}
- 应用配置状态:
- 像主题设置、语言偏好等,这些数据相对稳定且影响整个应用的外观和行为。使用Hive或SQLite存储。应用启动时,从存储中读取配置数据,并应用到整个应用。
- 示例(使用Hive):
// 初始化Hive
await Hive.initFlutter();
var box = await Hive.openBox('settingsBox');
// 保存主题设置
void saveTheme(String theme) {
box.put('theme', theme);
}
// 获取主题设置
String getTheme() {
return box.get('theme', defaultValue: 'light');
}
应对应用在后台运行、设备旋转等场景下的数据持久化与恢复问题
- 应用在后台运行:
- 数据持久化:在Flutter中,可通过监听
WidgetsBindingObserver
的 didChangeAppLifecycleState
方法,当应用进入后台(AppLifecycleState.paused
)时,将关键业务状态数据同步到数据库。例如,保存正在进行的任务进度等数据。
- 数据恢复:当应用从后台返回(
AppLifecycleState.resumed
)时,从数据库中读取保存的数据,并通过状态管理库恢复应用状态,通知UI更新。
- 示例:
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.paused) {
// 持久化数据到数据库
//...
} else if (state == AppLifecycleState.resumed) {
// 从数据库恢复数据
//...
}
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
//...
}
}
- 设备旋转:
- 数据持久化:对于设备旋转,Flutter本身会自动重建页面。但对于复杂的状态数据,可使用
AutomaticKeepAliveClientMixin
来保持状态。例如,在一个包含列表和详情的页面中,列表的滚动位置等状态可通过此方式保持。如果需要更复杂的数据持久化,可在旋转前将关键数据存储到数据库。
- 数据恢复:页面重建后,从
AutomaticKeepAliveClientMixin
保持的状态或数据库中恢复数据,使UI和业务状态回到旋转前的状态。
- 示例:
class MyPage extends StatefulWidget {
@override
_MyPageState createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
// 存储列表滚动位置
ScrollController _scrollController = ScrollController();
@override
void initState() {
super.initState();
// 从数据库或其他存储恢复滚动位置
//...
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
super.build(context);
return ListView(
controller: _scrollController,
children: [
//...
],
);
}
}