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

