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

Android非Activity类调用SharedPreferences工具类后台清理后崩溃

问题分析与解决方案

这个问题我太熟悉了!核心原因是你依赖了MainActivity的静态SharedPreferences实例——当APP从最近应用列表被移除后,系统大概率会杀掉你的App进程。之后BroadcastReceiver触发时,App进程会被重新拉起,但此时MainActivity并不会被初始化(因为不是通过启动Activity的方式唤起的),那个静态的SP实例自然就是null,调用它的方法肯定会崩溃。

下面给你两个靠谱的解决方案,按推荐程度排序:

方案1:用Application上下文获取SharedPreferences(最推荐)

Application的生命周期和整个App进程完全绑定,不会因为某个Activity销毁而失效,用它的上下文获取SP是最安全的做法。

步骤1:创建自定义Application类

public class MyApp extends Application {
    private static Context appContext;

    @Override
    public void onCreate() {
        super.onCreate();
        appContext = getApplicationContext();
    }

    public static Context getAppContext() {
        return appContext;
    }
}

步骤2:在Manifest中注册自定义Application

<application
    android:name=".MyApp"
    <!-- 其他原有属性保持不变 -->
    ...>
    <!-- 你的Activity、Receiver等注册信息 -->
</application>

步骤3:修改LocationRequestHelper类

彻底脱离对MainActivity的依赖,改用Application上下文获取SP:

public class LocationRequestHelper {
    private static final String PREF_NAME = "AppPrefs";
    private static final String KEY_USER_ID = "user_id";

    // 封装SP获取逻辑,内部用Application上下文
    private static SharedPreferences getSharedPreferences() {
        return MyApp.getAppContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
    }

    public static void setUserId(String userId) {
        getSharedPreferences().edit().putString(KEY_USER_ID, userId).apply();
    }

    public static String getUserId() {
        // 返回空字符串而非null,避免后续API调用出现空指针
        return getSharedPreferences().getString(KEY_USER_ID, "");
    }
}

这样不管是MainActivity调用setUserId,还是BroadcastReceiver触发Utils调用getUserId,都能稳定获取SP实例,就算进程被重新拉起,只要Application初始化完成(进程启动就会触发),SP就能正常工作。

方案2:直接传递Context到Helper方法(轻量替代)

如果不想自定义Application,也可以直接在调用Helper方法时传入有效的Context:

修改LocationRequestHelper类

public class LocationRequestHelper {
    private static final String PREF_NAME = "AppPrefs";
    private static final String KEY_USER_ID = "user_id";

    public static void setUserId(Context context, String userId) {
        context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
               .edit().putString(KEY_USER_ID, userId).apply();
    }

    public static String getUserId(Context context) {
        return context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
                      .getString(KEY_USER_ID, "");
    }
}

调用示例

  • 在MainActivity中:LocationRequestHelper.setUserId(this, "1")
  • 在BroadcastReceiver的onReceive方法中:LocationRequestHelper.getUserId(context)

这种方式也能避免依赖静态的Activity实例,只要传入的Context是有效的(比如Application上下文或者Receiver的上下文),就不会出现崩溃问题。

再帮你捋清崩溃的逻辑链

  1. APP在后台时,进程还存活,MainActivity的静态SP实例依然有效,调用正常;
  2. 从最近列表移除APP后,系统为释放内存杀掉App进程;
  3. 后续BroadcastReceiver触发时,系统仅拉起App进程并初始化Application和Receiver,不会启动MainActivity;
  4. 此时你在MainActivity中初始化的静态SP实例根本没被创建,是null,调用getUserId()时直接抛出NullPointerException导致崩溃。

内容的提问来源于stack exchange,提问作者Code Spy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:14:10