Flutter应用降级后sembast、shared_preferences存储数据丢失如何预防?
问题描述
我开发的Flutter应用使用sembast和shared_preferences存储本地数据,近期误操作降级应用版本后,所有已存储的本地数据全部丢失,该问题在物理设备和模拟器上均可复现。需要预防后续应用降级时出现同类数据丢失问题,不需要恢复已经丢失的历史数据。
复现步骤
- 新建Flutter项目
- 向shared_preferences或sembast中写入存储数据
- 执行热重启操作
- 将应用构建号修改为低于当前版本的数值,例如从1.0.0+110改为1.0.0+109
- 再次执行热重启即可复现数据丢失问题
项目依赖(pubspec.yaml)
version: 1.0.0+111 environment: sdk: ">=2.9.0 <3.0.0" dependencies: flutter: sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.3 excel: ^2.0.0-null-safety-3 shared_preferences: ^2.0.6 permission_handler: ^8.1.1 path_provider: ^2.0.2 sembast: ^3.1.0+2 sembast_web: ^2.0.0+2 #remove web version not being used intl: ^0.17.0 provider: ^5.0.0 firebase_core: ^1.3.0 firebase_analytics: ^8.1.2 firebase_performance: ^0.7.0+5 firebase_crashlytics: ^2.0.6 firebase_auth: ^1.4.1 get_it: ^7.1.3 open_file: ^3.2.1 flutter_bloc: ^7.0.1 cloud_firestore: ^2.2.2 #remove and maybe use cloud functions syncfusion_flutter_charts: ^19.1.69+1 url_launcher: ^6.0.3 file_picker: ^3.0.3 flutter_typeahead: ^3.1.3 purchases_flutter: ^3.3.0 device_info_plus: ^2.0.1
运行环境(flutter doctor输出)
[√] Flutter (Channel stable, 2.2.2, on Microsoft Windows [Version 10.0.19043.1081], locale en-IN) • Flutter version 2.2.2 at D:\Applications\flutter • Framework revision d79295af24 (2 weeks ago), 2021-06-11 08:56:01 -0700 • Engine revision 91c9fc8fe0 • Dart version 2.13.3 [√] Android toolchain - develop for Android devices (Android SDK version 31.0.0-rc1) • Android SDK at D:\Applications\Android-SDK • Platform android-S, build-tools 31.0.0-rc1 • Java binary at: D:\Applications\Android_studio\jre\bin\java • Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6842174) • All Android licenses accepted. [√] Chrome - develop for the web • Chrome at C:\Program Files (x86)\Google\Chrome\Application\chrome.exe [√] Android Studio (version 4.1.0) • Android Studio at D:\Applications\Android_studio • Flutter plugin can be installed from: https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6842174) [√] Connected device (3 available) • sdk gphone x86 (mobile) • emulator-5554 • android-x86 • Android 11 (API 30) (emulator) • Chrome (web) • chrome • web-javascript • Google Chrome 91.0.4472.114 • Edge (web) • edge • web-javascript • Microsoft Edge 91.0.864.37 • No issues found!
解决方案
该问题是Android平台默认的自动备份机制导致的:系统判定安装包版本低于设备现有版本时,会默认清除应用私有目录下的所有数据,而sembast和shared_preferences的存储路径均属于应用私有目录,因此会被清空。iOS平台不存在该系统级逻辑,以下方案仅针对Android端生效:
1. 直接关闭系统自动备份功能
在Android项目android/app/src/main/AndroidManifest.xml的application标签中添加android:allowBackup="false"配置,从根源避免降级触发数据清除:
<application android:name="io.flutter.app.FlutterApplication" android:label="你的应用名称" android:icon="@mipmap/ic_launcher" <!-- 新增下面这行配置 --> android:allowBackup="false"> <!-- 其他原有配置保持不变 --> </application>
如果你需要保留系统自动备份功能,可以新增android:fullBackupOnly="false"配置,同时自定义备份规则将本地存储路径加入免清除白名单即可。
2. 手动实现数据冗余备份
如果不想修改系统备份配置,可以自己实现备份逻辑:
- 每次应用启动时,将
sembast数据库文件和shared_preferences的全量数据备份一份到应用公共存储目录,备份文件命名关联当前应用版本号 - 应用启动时优先校验私有目录下的存储数据完整性,若数据丢失则自动从公共目录的备份文件恢复
3. 规范版本发布流程
- 正式发布的安装包严格保证版本号、构建号单调递增,禁止提交版本号低于历史版本的安装包到应用市场
- 开发测试阶段如需安装低版本包,先手动卸载设备上的高版本应用,避免触发系统降级清数据逻辑
内容的提问来源于stack exchange,提问作者Nishuthan S
相关产品推荐
相关产品推荐

