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

Kotlin单例使用遇错求助:SharedPreferences空指针等问题

问题分析与解决方案

从堆栈信息可知,核心错误是java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.SharedPreferences android.content.Context.getSharedPreferences(java.lang.String, int)' on a null object reference,根源在于手动实例化MainActivity()获取Context的方式完全错误——Android中的Activity实例必须由系统框架创建,手动new出来的Activity未完成初始化流程,其Context为null,直接调用getSharedPreferences必然触发空指针。

而第一个调用单例出错的问题,本质是单例Data初始化失败(ExceptionInInitializerError)引发的连锁反应,修复SharedPreferences的初始化问题后,该调用错误会自动解决。

具体修复步骤

1. 修复SharedPreferences初始化逻辑

放弃手动创建Activity实例,改用Application Context获取SharedPreferences,同时用Kotlin的lazy委托实现延迟初始化,避免单例初始化时依赖未就绪的Context:

object Data {
    // Format: <Device Address, Name>
    var names: MutableMap<String, String> = mutableMapOf()

    // Format: <Device Address>
    var addresses = mutableSetOf<String>()

    private lateinit var appContext: Context
    // 延迟初始化,确保Context就绪后再创建SharedPreferences实例
    val sharedPref: SharedPreferences by lazy {
        appContext.getSharedPreferences("MySharedPreferencesFile", Context.MODE_PRIVATE)
    }

    // 初始化入口,在Application启动时调用
    fun initialize(context: Context) {
        appContext = context.applicationContext
    }

    // ... 其他代码
}

接下来创建自定义Application类(若已有则直接修改),在onCreate中完成单例初始化:

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        Data.initialize(this)
    }
}

最后在AndroidManifest.xml中指定该Application:

<application
    android:name=".MyApp"
    <!-- 其他原有属性 -->
    >
    <!-- 活动声明 -->
</application>

2. 优化saveSharedPreferences的空安全与性能

原代码中!sharedPref?.contains(key)!!存在空指针风险,且多次调用edit()和apply()会降低性能,优化后如下:

fun saveSharedPreferences() {
    val editor = sharedPref.edit()
    for ((key, value) in names) {
        if (!sharedPref.contains(key)) {
            editor.putString(key, value)
        }
    }
    editor.apply() // 统一提交编辑操作,提升性能
}

3. 验证单例调用逻辑

原调用代码Data.addresses.add(address)本身无语法问题,完成上述修复、单例Data初始化成功后,该调用即可正常工作。

修复逻辑说明

  • Application Context优势:其生命周期与应用一致,不会因Activity销毁而失效,适合单例持有。
  • 延迟初始化:确保sharedPref在真正需要使用时才初始化,规避单例加载时的Context就绪问题。
  • 空安全与性能优化:移除不必要的!!操作符,批量提交SharedPreferences编辑操作,兼顾安全与效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 15:54:53