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

如何在应用完全关闭而非转入后台时使用SharedPreferences存储数据?

解决方案:区分应用后台切换与完全关闭时的数据存储

嘿,这个问题我之前做应用的时候也踩过坑!确实,onPause()和onStop()触发太频繁了,切个后台就跑,根本没法区分用户是暂时切换应用还是真的要完全关掉它。下面给你几个亲测好用的方案:

1. 监听主动关闭事件:onTaskRemoved()

这个方法简直是为用户主动关闭App量身定做的!当用户从最近任务列表里把你的App划掉时,系统会调用Service中的onTaskRemoved()方法,完美匹配你要的「完全关闭」场景:

  • 写一个轻量的服务(Android 8.0+建议用前台服务,避免被系统限制),重写该方法:
class AppCloseMonitorService : Service() {
    override fun onBind(intent: Intent?): IBinder? = null

    override fun onTaskRemoved(rootIntent: Intent?) {
        super.onTaskRemoved(rootIntent)
        // 在这里完成SharedPreferences数据存储
        val sharedPref = getSharedPreferences("app_data", Context.MODE_PRIVATE)
        with(sharedPref.edit()) {
            putString("user_preference", "your_value")
            apply() // 用apply()异步写入,系统会兜底完成,比commit()更安全
        }
        stopSelf() // 任务完成后停止服务
    }
}
  • 在主Activity的onCreate()里启动这个服务:
startService(Intent(this, AppCloseMonitorService::class.java))

如果是前台服务,只需要加个透明通知就行,用户几乎感知不到。

2. 统计活跃Activity数量,判断真正退出

通过Application.ActivityLifecycleCallbacks监听所有Activity的生命周期,统计当前活跃的Activity数量。当数量归0且一段时间内没有新Activity启动,就判定为完全关闭:

  • 自定义Application类,注册生命周期回调:
class MyApp : Application() {
    private var activeActivityCount = 0
    private var isAppInBackground = false

    override fun onCreate() {
        super.onCreate()
        registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
            override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
                activeActivityCount++
            }

            override fun onActivityStarted(activity: Activity) {
                activeActivityCount++
                isAppInBackground = false
            }

            override fun onActivityStopped(activity: Activity) {
                activeActivityCount--
                if (activeActivityCount == 0) {
                    isAppInBackground = true
                    // 延迟3秒检查,避免把后台切换误判为完全关闭
                    Handler(Looper.getMainLooper()).postDelayed({
                        if (activeActivityCount == 0 && isAppInBackground) {
                            // 执行数据存储逻辑
                            val sharedPref = getSharedPreferences("app_data", Context.MODE_PRIVATE)
                            with(sharedPref.edit()) {
                                putString("user_preference", "your_value")
                                apply()
                            }
                        }
                    }, 3000)
                }
            }

            // 其他生命周期方法可空实现
            override fun onActivityResumed(activity: Activity) {}
            override fun onActivityPaused(activity: Activity) {}
            override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle?) {}
            override fun onActivityDestroyed(activity: Activity) {}
        })
    }
}

这个方案不需要依赖Service,适合不想加服务的场景,延迟时间可以根据你的需求调整。

3. 结合ProcessLifecycleOwner监听进程状态

如果你用了Android Jetpack,ProcessLifecycleOwner可以监听整个应用的进程生命周期,覆盖系统杀死进程的场景:

  • 先添加依赖(如果还没加):
implementation "androidx.lifecycle:lifecycle-process:2.6.2"
  • 在Application中注册监听:
class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
            override fun onDestroy(owner: LifecycleOwner) {
                super.onDestroy(owner)
                // 进程即将销毁时存储数据
                val sharedPref = getSharedPreferences("app_data", Context.MODE_PRIVATE)
                with(sharedPref.edit()) {
                    putString("user_preference", "your_value")
                    apply()
                }
            }
        })
    }
}

注意:系统内存不足杀进程时,onDestroy()可能不会触发,所以建议和onTaskRemoved()结合使用,覆盖主动关闭和被动杀死的所有场景。

最后小提醒

存储数据时一定要用apply()而不是commit()!commit()是同步写入,可能阻塞主线程;apply()是异步的,即使进程被杀,Android系统也会在后续帮你完成写入,数据不会丢失。

内容的提问来源于stack exchange,提问作者Isaac Walling

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:43:06