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

SingletonInstance未赋值?Android单例空指针问题排查

问题分析与解决方案

核心结论

是的,SingletonInstance::set()从未被调用过,这就是触发异常的根源。

问题原因拆解

  1. 委托仅提供属性逻辑,不自动初始化实例:
    ServiceClientCtxConf的伴生对象通过by SingletonInstance()委托实现了ISingletonInstance接口,这仅让ServiceClientCtxConf.instance的get/set操作转发给SingletonInstance类的对应方法,但不会自动创建ServiceClientCtxConf的实例并完成赋值。
  2. 未执行赋值操作:
    你的代码中没有任何地方执行ServiceClientCtxConf.instance = ServiceClientCtxConf(...),导致SingletonInstance内部的singletonInstance始终为null,调用get()时就会触发ConfException: ... is NULL!。

可行解决方案

方案1:手动提前初始化

在应用启动阶段(比如Application的onCreate方法)手动创建实例并赋值:

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // 初始化单例实例
        ServiceClientCtxConf.instance = ServiceClientCtxConf()
    }
}

方案2:修改SingletonInstance支持懒加载

如果希望单例在第一次被使用时自动创建,可以修改SingletonInstance的实现,传入实例创建逻辑:

interface ISingletonInstance<T> {
    var instance: T
}

class SingletonInstance<T : Any>(private val creator: () -> T) : ISingletonInstance<T> {
    private var singletonInstance: T? = null

    override var instance: T
        set(value) {
            singletonInstance = value
        }
        get() = singletonInstance ?: creator().also { singletonInstance = it }
}

// 对应修改ServiceClientCtxConf的伴生对象:
class ServiceClientCtxConf(
    val serviceClient: IServiceClient = ServiceClient()
) {
    companion object : ISingletonInstance<ServiceClientCtxConf> by SingletonInstance { ServiceClientCtxConf() }
}

方案3:改用Kotlin原生object单例

如果不需要动态修改单例实例(绝大多数单例场景都不需要),直接用Kotlin的object声明更简洁可靠:

object ServiceClientCtxConf {
    val serviceClient: IServiceClient = ServiceClient()
}

// 使用时直接调用:
ServiceClientConf.setConf(context = ServiceClientCtxConf)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 18:02:41