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

Kotlin Activity中SharedPreferences加载Spinner数据崩溃求助

解决Activity初始化时SharedPreferences空指针问题

看起来你遇到的空指针问题很典型——在Activity的Context还没完全初始化完成时,就尝试获取SharedPreferences。咱们一步步来解决:

问题根源

你用by lazy初始化sharedPreferences和dataModel,而lazy初始化会在第一次访问这些变量时执行。但Activity的Context在onCreate()方法执行前还没准备好,当系统尝试实例化你的CarbsInput Activity时,这些lazy属性会被触发,调用getSharedPreferences()就会抛出NullPointerException,因为此时this(Activity Context)还不是一个有效的上下文对象。

修复方案

我们需要把SharedPreferences和CarbsInputModel的初始化延后到onCreate()执行之后,确保Context已经可用。这里有两种简单的实现方式:

方式1:延迟初始化(改用lateinit)

把sharedPreferences和dataModel改成lateinit var,在onCreate()里完成初始化:

class CarbsInput : AppCompatActivity(), AdapterView.OnItemSelectedListener {
    var spinner: Spinner? = null
    var spinner2: Spinner? = null
    val sharedPrefFile = "greenbandbasicpreference"
    lateinit var sharedPreferences: SharedPreferences
    lateinit var dataModel: CarbsInputModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.input_carbs)
        
        // 现在Context已经可用,初始化SharedPreferences和Model
        sharedPreferences = getSharedPreferences(sharedPrefFile, MODE_PRIVATE)
        dataModel = CarbsInputModel(sharedPreferences)
        
        // 剩下的原有代码...
        spinner = this.gi_spinner
        spinner2 = this.carbs_per_spinner
        val aa = ArrayAdapter(this, android.R.layout.simple_spinner_item, dataModel.gIndices)
        // ...后续代码不变
    }

    // 其他方法(onItemSelected、enterCarbs等)保持不变
}

方式2:改进lazy初始化的条件(确保Context就绪)

如果你还是想用lazy,可以给lazy块加上条件,确保只有在Activity已经创建完成后才初始化:

val sharedPreferences: SharedPreferences by lazy { 
    checkNotNull(this.applicationContext) { "Context not ready yet" }
    getSharedPreferences(sharedPrefFile, MODE_PRIVATE) 
}
val dataModel: CarbsInputModel by lazy { 
    CarbsInputModel(sharedPreferences) 
}

不过更推荐第一种lateinit的方式,逻辑更清晰,也更符合Android组件的生命周期规范。

额外优化建议

  • 你整理的onItemSelected用when替代嵌套if-else的写法非常好,比原来的代码更简洁易读,直接替换原来的方法就行。
  • 注意在处理EditText的文本转Long时,最好加上非空和格式校验,避免用户输入非数字内容导致崩溃,比如可以用toLongOrNull()替代toLong():
    var carbPer = et_carbsper.text.toString().toLongOrNull() ?: 0L
    var weight = et_weight.text.toString().toLongOrNull() ?: 0L
    

这样修改后,你的Activity就能正常启动,不会再因为空指针崩溃了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 18:08:15