You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter应用全新安装后SharedPreferences存在username键的异常问题

Flutter SharedPreferences卸载重装后仍保留数据的问题排查与解决

问题描述

应用首次启动时,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>

可能原因

  1. Android Auto Backup默认开启:Android 6.0(API 23)及以上系统默认开启自动备份功能,会将应用数据(包括SharedPreferences)备份到云端,卸载重装时自动恢复数据
  2. 厂商定制备份机制:部分国产安卓厂商(如小米、华为)提供了额外的应用数据备份功能,卸载应用时未彻底清除本地存储的数据
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 11:17:45