Flutter应用全新安装后SharedPreferences存在username键的异常问题
问题描述
应用首次启动时,AuthScreen通过SharedPreferences检查localStorage中是否存在username键:存在则跳转至TabsScreen,不存在则跳转至LoginScreen。但出现以下异常:
- 模拟器全新安装时功能正常
- 真机安装
app-release.apk后,全新安装状态下localStorage中已存在username键,直接跳转至TabsScreen - 手动清除应用数据后恢复正常,但卸载重装后问题复现
- 两台测试安卓设备中,一台安装
app-debug.apk后恢复正常,另一台仍有问题
相关代码
AuthScreen代码
import 'package:distributor_obat_semarang/screens/login.dart'; import 'package:distributor_obat_semarang/screens/splash.dart'; import 'package:distributor_obat_semarang/screens/tabs.dart'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class AuthScreen extends StatefulWidget { const AuthScreen({super.key}); @override State<AuthScreen> createState() => _CheckAuthScreenState(); } class _CheckAuthScreenState extends State<AuthScreen> { final Future<SharedPreferences> _prefs = SharedPreferences.getInstance(); late Future<bool> loginCheckFuture; Future<bool> _checkIfLoggedIn() async { final SharedPreferences prefs = await _prefs; var isAuth = prefs.getString('username'); if (isAuth != null) { return true; } return false; } @override void initState() { super.initState(); loginCheckFuture = _checkIfLoggedIn(); } @override Widget build(BuildContext context) { Widget child; return FutureBuilder( future: loginCheckFuture, builder: (context, snapshot) { if (snapshot.hasData) { if (snapshot.data == true) { child = const TabsScreen(); } else { child = const LoginScreen(); } } else { child = const SplashScreen(); } return Scaffold( body: child, ); }, ); } }
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <uses-permission android:name="android.permission.INTERNET"/> <application android:label="Distributor Obat Semarang" android:name="${applicationName}" android:icon="@mipmap/launcher_icon"> <activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize"> <meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme" /> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <meta-data android:name="flutterEmbedding" android:value="2" /> </application> </manifest>
可能原因
- Android Auto Backup默认开启:Android 6.0(API 23)及以上系统默认开启自动备份功能,会将应用数据(包括
SharedPreferences)备份到云端,卸载重装时自动恢复数据 - 厂商定制备份机制:部分国产安卓厂商(如小米、华为)提供了额外的应用数据备份功能,卸载应用时未彻底清除本地存储的数据
- Release包编译优化:Release模式下的编译优化可能导致
SharedPreferences的初始化逻辑出现异常,未正确识别全新安装状态
解决方案
方案1:禁用Android自动备份
修改AndroidManifest.xml的application标签,添加备份相关配置:
<application android:label="Distributor Obat Semarang" android:name="${applicationName}" android:icon="@mipmap/launcher_icon" android:allowBackup="false" android:fullBackupContent="false"> <!-- 原有内容保持不变 --> </application>
android:allowBackup="false":关闭应用的自动备份功能android:fullBackupContent="false":明确指定不备份任何应用内容
方案2:添加首次安装校验逻辑
在登录检查逻辑中增加首次安装标识,确保全新安装时清空所有存储数据:
修改_checkIfLoggedIn方法:
Future<bool> _checkIfLoggedIn() async { final SharedPreferences prefs = await _prefs; bool isFirstInstall = prefs.getBool('is_first_install') ?? true; if (isFirstInstall) { // 首次安装,清空所有存储数据 await prefs.clear(); // 标记为已完成首次安装 await prefs.setBool('is_first_install', false); return false; } var isAuth = prefs.getString('username'); return isAuth != null; }
该逻辑会在首次安装时强制清空所有SharedPreferences数据,确保不会残留旧数据。
方案3:检查设备备份设置
对于出现问题的测试设备,进入系统设置 -> 应用管理 -> 对应应用 -> 关闭"自动备份"或"云同步"功能,确保卸载时彻底清除应用数据。
内容的提问来源于stack exchange,提问作者Septatrivanto Wandy
相关产品推荐
相关产品推荐

